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

📄 ovfx2.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}static intsensor_set_control(struct usb_ovfx2 *ov, int cid, int val){	struct ovcamchip_control ctl;	int rc;	if (sensor_needs_stop(ov, cid))		if (ovfx2_pause(ov) < 0)			return -EIO;	ctl.id = cid;	ctl.value = val;	rc = sensor_cmd(ov, OVCAMCHIP_CMD_S_CTRL, &ctl);	if (ovfx2_resume(ov) < 0)		return -EIO;	return rc;}static intsensor_get_control(struct usb_ovfx2 *ov, int cid, int *val){	struct ovcamchip_control ctl;	int rc;	ctl.id = cid;	rc = sensor_cmd(ov, OVCAMCHIP_CMD_G_CTRL, &ctl);	if (rc >= 0)		*val = ctl.value;	return rc;}static intsensor_set_picture(struct usb_ovfx2 *ov, struct video_picture *p){	int rc;	PDEBUG(4, "sensor_set_picture");	rc = reg_w(ov, REG_CNTR, p->contrast >> 8);	if (rc < 0)		return rc;	rc = reg_w(ov, REG_BRIGHT, (p->brightness >> 8) - 127);	if (rc < 0)		return rc;	rc = reg_w(ov, REG_SAT, p->colour >> 8);	if (rc < 0)		return rc;	rc = reg_w(ov, REG_HUE, (p->hue >> 8) - 127);	if (rc < 0)		return rc;	return 0;}static intsensor_get_picture(struct usb_ovfx2 *ov, struct video_picture *p){	int rc;	PDEBUG(4, "sensor_get_picture");	/* Don't return error if a setting is unsupported, or rest of settings         * will not be performed */	rc = reg_r(ov, REG_CNTR);	if (rc < 0)		return rc;	p->contrast = rc << 8;	rc = reg_r(ov, REG_BRIGHT);	if (rc < 0)		return rc;	p->brightness = (rc + 127) << 8;	rc = reg_r(ov, REG_SAT);	if (rc < 0)		return rc;	p->colour = rc << 8;	rc = reg_r(ov, REG_HUE);	if (rc < 0)		return rc;	p->hue = (rc + 127) << 8;	p->whiteness = 105 << 8;	return 0;}/* Matches the sensor's internal frame rate to the lighting frequency. * Valid frequencies are: *	50 - 50Hz, for European and Asian lighting *	60 - 60Hz, for American lighting * * Returns: 0 for success */static intsensor_set_light_freq(struct usb_ovfx2 *ov, int freq){	if (freq != 50 && freq != 60) {		err("Invalid light freq (%d Hz)", freq);		return -EINVAL;	}	return sensor_set_control(ov, OVCAMCHIP_CID_FREQ, freq);}/* Returns number of bits per pixel (regardless of where they are located; * planar or not), or zero for unsupported format. */static inline intget_depth(int palette){	switch (palette) {	case VIDEO_PALETTE_RGB24:	return 24; /* Planar */	default:			return 0;  /* Invalid format */	}}/* Bytes per frame. Used by read(). Return of 0 indicates error */static inline long intget_frame_length(struct ovfx2_frame *frame){	if (!frame)		return 0;	else		return ((frame->width * frame->height			 * get_depth(frame->format)) >> 3);}static intset_ov_sensor_window(struct usb_ovfx2 *ov, int width, int height, int mode,		     int sub_flag){	struct ovcamchip_window win;	int rc;	win.format = mode;	/* Unless subcapture is enabled, center the image window and downsample	 * if possible to increase the field of view */	if (sub_flag) {		win.x = ov->subx;		win.y = ov->suby;		win.width = ov->subw;		win.height = ov->subh;		win.quarter = 0;	} else {		win.x = 0;		win.y = 0;		win.width = ov->maxwidth;		win.height = ov->maxheight;		win.quarter = 0;	}	if (clockdiv >= 0)		win.clockdiv = clockdiv;	else		win.clockdiv = 0x01;	/* Always use the max frame rate */	rc = sensor_cmd(ov, OVCAMCHIP_CMD_S_MODE, &win);	if (rc < 0)		return rc;	if (framedrop >= 0)		i2c_w(ov, 0x16, framedrop);	return 0;}/* Sets up the OVFX2 with the given image parameters */static intovfx2_mode_init_regs(struct usb_ovfx2 *ov,		     int width, int height, int mode, int sub_flag){	if (sub_flag) {		width = ov->subw;		height = ov->subh;	}	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",	       width, height, mode, sub_flag);	if (width < ov->minwidth || height < ov->minheight) {		err("Requested dimensions are too small");		return -EINVAL;	}	/* Set palette */	/* Set bus width */	/* Set resolution */	/* Set framerate/clock */	reg_w_mask(ov, 0x0f, 0x08, 0x08);	/* Reinitialize? */	return 0;}/* This is a wrapper around the FX2 and sensor specific functions */static intmode_init_regs(struct usb_ovfx2 *ov,	       int width, int height, int mode, int sub_flag){	int rc = 0;	rc = ovfx2_mode_init_regs(ov, width, height, mode, sub_flag);	if (FATAL_ERROR(rc))		return rc;	rc = set_ov_sensor_window(ov, width, height, mode, sub_flag);	if (FATAL_ERROR(rc))		return rc;	/********* The following settings are specific to this camera ********/	i2c_w(ov, 0x03, 0x80);		  /* Hardcoded saturation value */	i2c_w_mask(ov, 0x12, 0x48, 0x48); /* Enable h-mirror and raw output */	i2c_w_mask(ov, 0x27, 0x10, 0x10); /* Bypass RGB matrix */	i2c_w_mask(ov, 0x28, 0x04, 0x04); /* G/BR (YG) mode */	i2c_w_mask(ov, 0x2a, 0x00, 0x10); /* No UV 2-pixel delay */	i2c_w_mask(ov, 0x2d, 0x40, 0x40); /* QVGA 60 FPS (redundant?) */	i2c_w(ov, 0x67, 0x00); 		  /* Disable YUV postprocess */	i2c_w_mask(ov, 0x2d, 0x00, 0x0f); /* Disable anti-alias */	i2c_w(ov, 0x24, 0x20); 		  /* Use QVGA white pixel ratio */	i2c_w(ov, 0x25, 0x30); 		  /* Use QVGA black pixel ratio */	i2c_w(ov, 0x60, 0x26);		  /* Unknown */	i2c_w(ov, 0x74, 0x20);		  /* AGC max gain = 4x */	i2c_w(ov, 0x06, 0x68);		  /* Hardcoded brightness value */	i2c_w(ov, 0x14, 0x04);		  /*  */	return 0;}/* Set up the camera chip with the options provided by the module params */static intcamchip_init_settings(struct usb_ovfx2 *ov){	int rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_AUTOBRIGHT, autobright);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_AUTOEXP, autoexp);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_BANDFILT, bandingfilter);	if (FATAL_ERROR(rc))		return rc;	if (lightfreq) {		rc = sensor_set_light_freq(ov, lightfreq);		if (FATAL_ERROR(rc))			return rc;	}	rc = sensor_set_control(ov, OVCAMCHIP_CID_BACKLIGHT, backlight);	if (FATAL_ERROR(rc))		return rc;	rc = sensor_set_control(ov, OVCAMCHIP_CID_MIRROR, mirror);	if (FATAL_ERROR(rc))		return rc;	return 0;}/* This sets the default image parameters. This is useful for apps that use * read() and do not set these. */static intovfx2_set_default_params(struct usb_ovfx2 *ov){	int i;	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used	 * (using read() instead). */	for (i = 0; i < OVFX2_NUMFRAMES; i++) {		ov->frame[i].width = ov->maxwidth;		ov->frame[i].height = ov->maxheight;		if (force_palette)			ov->frame[i].format = force_palette;		else			ov->frame[i].format = VIDEO_PALETTE_RGB24;		ov->frame[i].depth = get_depth(ov->frame[i].format);	}	PDEBUG(3, "%dx%d, %s", ov->maxwidth, ov->maxheight,	       symbolic(v4l1_plist, ov->frame[0].format));	/* Initialize to max width/height, default palette */	if (mode_init_regs(ov, ov->maxwidth, ov->maxheight,			   ov->frame[0].format, 0) < 0)		return -EINVAL;	return 0;}#if defined(HAVE_V4L2)static int ovfx2_control_op(struct usb_ovfx2 *ov, unsigned int cmd, void *arg){	/* No controls defined yet */	return -EINVAL;}#endif/********************************************************************** * * Frame buffering * **********************************************************************//* Sleeps until no frames are active. Returns !0 if got signal or unplugged */static intov51x_wait_frames_inactive(struct usb_ovfx2 *ov){	int rc;	rc = wait_event_interruptible(ov->wq, ov->curframe < 0 || !ov->present);	if (rc)		return rc;	if (ov->present)		return 0;	else		return -ENODEV;}/********************************************************************** * * Raw data parsing * **********************************************************************/static voidgbgr_to_bgr24(struct ovfx2_frame *frame,	      unsigned char *pIn,	      unsigned char *pOut){	const unsigned int a = frame->rawwidth * frame->rawheight / 2;	int i;	for (i = 0; i < a; i++) {		pOut[0] = pIn[1];		pOut[1] = pIn[0];		pOut[2] = pIn[3];		pOut[3] = pIn[1];		pOut[4] = pIn[2];		pOut[5] = pIn[3];		pIn += 4;		pOut += 6;	}}/* Flip image vertically */static voidvert_mirror(unsigned char *pIn,	    unsigned char *pOut,	    unsigned int width,	    unsigned int height,	    unsigned int depth){	const unsigned int linesize = width * depth;	int i;	pOut += height * linesize;	for (i = 0; i < height; i++) {		pOut -= linesize;		memcpy(pOut, pIn, linesize);		pIn += linesize;	}}/********************************************************************** * * Image processing * **********************************************************************/static voidovfx2_postprocess(struct usb_ovfx2 *ov, struct ovfx2_frame *frame){	if (dumppix == 1) {		/* Dump with color decoding */		memset(frame->data, 0,			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));		PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);		gbgr_to_bgr24(frame, frame->rawdata, frame->data);	} else if (dumppix == 2) {	/* Dump raw data */		memset(frame->data, 0,			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));		PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);		memcpy(frame->data, frame->rawdata, frame->bytes_recvd);	} else {//		/* FIXME: Remove this once decoding is stable *///		memset(frame->data, 0,//			MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));//		memset(frame->tempdata, 0,//			MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight));		vert_mirror(frame->rawdata, frame->tempdata, frame->rawwidth,			    frame->rawheight, 2);		gbgr_to_bgr24(frame, frame->tempdata, frame->data);	}}/********************************************************************** * * OV51x data transfer, IRQ handler * **********************************************************************/static inline voidovfx2_move_data(struct usb_ovfx2 *ov, unsigned char *in, int n){	int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);	struct ovfx2_frame *frame = &ov->frame[ov->curframe];	struct timeval *ts;//	info("bytes_recvd = %d;  n = %d", frame->bytes_recvd, n);	if (frame->scanstate == STATE_LOCKED) {		PDEBUG(4, "Starting capture on frame %d", frame->framenum);		frame->scanstate = STATE_RECEIVING;		frame->bytes_recvd = 0;	}	if (n) {		int b = n;	/* Number of image data bytes */#if 1		/* The first 2560 bytes of data (first 2 lines?) are invalid */		if (frame->bytes_recvd == 0) {			in += 2560;			b -= 2560;		}#endif		frame->bytes_recvd += b;		if (frame->bytes_recvd <= max_raw)			memcpy(frame->rawdata + frame->bytes_recvd - b, in, b);		else			PDEBUG(5, "Raw data buffer overrun!! (%d)",				frame->bytes_recvd - max_raw);	} else {		PDEBUG(5, "Empty bulk packet");	}	/* Short packets indicate EOF */	if (n < OVFX2_BULK_SIZE) {    		int nextf;		PDEBUG(4, "Frame end, curframe = %d, recvd=%d",			ov->curframe, frame->bytes_recvd);#if 1		if (frame->bytes_recvd < max_raw) {			PDEBUG(3, "Frame was short; discarding");			frame->bytes_recvd = 0;			frame->grabstate = FRAME_ERROR;			wake_up_interruptible(&frame->wq);			return;		}#endif		/* Don't allow byte count to exceed buffer size */		RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);		ts = (struct timeval *)(frame->data		      + MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));		do_gettimeofday(ts);		// FIXME: Since we don't know the header formats yet,		// there is no way to know what the actual image size is		frame->rawwidth = frame->width;		frame->rawheight = frame->height;		/* Don't wake up user for same frame more than once */		if (frame->grabstate != FRAME_DONE) {			frame->grabstate = FRAME_DONE;			wake_up_interruptible(&frame->wq);		}		/* If next frame is ready or grabbing, point to it */		nextf = (ov->curframe + 1) % OVFX2_NUMFRAMES;		if (ov->frame[nextf].grabstate == FRAME_READY		    || ov->frame[nextf].grabstate == FRAME_GRABBING) {			ov->curframe = nextf;			ov->frame[nextf].bytes_recvd = 0;			ov->frame[nextf].scanstate = STATE_LOCKED;		} else {			if (ov->frame[nextf].grabstate == FRAME_DONE) {				PDEBUG(4, "No empty frames left");			} else {				PDEBUG(4, "Frame not ready? state = %d",				       ov->frame[nextf].grabstate);			}			ov->curframe = -1;		}	}}static void#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 51)ovfx2_bulk_irq(struct urb *urb, struct pt_regs *regs)#elseovfx2_bulk_irq(struct urb *urb)#endif{	int i;	int actlen = urb->actual_length;	struct usb_ovfx2 *ov;	struct ovfx2_sbuf *sbuf;	if (!urb->context) {		PDEBUG(4, "no context");		return;	}	sbuf = urb->context;	ov = sbuf->ov;	if (!ov || !ov->dev || !ov->user) {		PDEBUG(4, "no device, or not open");		return;	}	if (!ov->streaming) {		PDEBUG(4, "hmmm... not streaming, but got interrupt");		return;	}        if (urb->status == -ENOENT || urb->status == -ECONNRESET) {                PDEBUG(4, "URB unlinked");                return;        }

⌨️ 快捷键说明

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