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

📄 ovfx2.c

📁 支持linux2.6和linux2.4的ov511摄像头驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (urb->status != -EINPROGRESS && urb->status != 0) {		err("ERROR: urb->status=%d: %s", urb->status,		    symbolic(urb_errlist, urb->status));	}	PDEBUG(5, "sbuf[%d]: Got bulk completion: actlen=%d", sbuf->n, actlen);	/* Warning: Don't copy data if no frame active! */	if (ov->curframe >= 0) {		ovfx2_move_data(ov, urb->transfer_buffer, actlen);	} else if (waitqueue_active(&ov->wq)) {		wake_up_interruptible(&ov->wq);	}	/* Resubmit this URB */	urb->status = 0; // FIXME: Is this necessary? What about w/ OV511/OV518?	urb->dev = ov->dev;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)	if ((i = usb_submit_urb(urb, GFP_ATOMIC)) != 0)#else	if ((i = usb_submit_urb(urb)) != 0)#endif		err("usb_submit_urb() ret %d", i);	return;}/**************************************************************************** * * Stream initialization and termination * ***************************************************************************/static intovfx2_start_stream(struct usb_ovfx2 *ov){	struct urb *urb;	int err, n, size;	PDEBUG(3, "*** Starting video stream ***");	/* Start stream */	err = reg_w_mask(ov, 0x0f, 0x02, 0x02);	if (err)		return err;	ov->curframe = -1;	size = OVFX2_BULK_SIZE;	for (n = 0; n < OVFX2_NUMSBUF; n++) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 5)		urb = usb_alloc_urb(0, GFP_KERNEL);#else		urb = usb_alloc_urb(0);#endif		if (!urb) {			err("start stream: usb_alloc_urb ret. NULL");			return -ENOMEM;		}		usb_fill_bulk_urb(urb,				  ov->dev,				  usb_rcvbulkpipe(ov->dev,						  OVFX2_BULK_ENDPOINT_ADDR),				  ov->sbuf[n].data,				  size,				  ovfx2_bulk_irq,				  &ov->sbuf[n]);		ov->sbuf[n].urb = urb;	}	ov->streaming = 1;	for (n = 0; n < OVFX2_NUMSBUF; n++) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 4)		err = usb_submit_urb(ov->sbuf[n].urb, GFP_KERNEL);#else		err = usb_submit_urb(ov->sbuf[n].urb);#endif		if (err) {			err("start stream: usb_submit_urb(%d) ret %d", n, err);			return err;		}	}	return 0;}static voidovfx2_unlink_bulk(struct usb_ovfx2 *ov){	int n;	/* Unschedule all of the bulk td's */	for (n = OVFX2_NUMSBUF - 1; n >= 0; n--) {		if (ov->sbuf[n].urb) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 8)			usb_kill_urb(ov->sbuf[n].urb);#else			usb_unlink_urb(ov->sbuf[n].urb);#endif			usb_free_urb(ov->sbuf[n].urb);			ov->sbuf[n].urb = NULL;		}	}}static intovfx2_stop_stream(struct usb_ovfx2 *ov){	if (!ov->streaming)		return -ENODEV;	PDEBUG(3, "*** Stopping capture ***");	ov->streaming = 0;	ovfx2_unlink_bulk(ov);	/* Stop stream */	return reg_w_mask(ov, 0x0f, 0x00, 0x02);}static intovfx2_new_frame(struct usb_ovfx2 *ov, int framenum){	struct ovfx2_frame *frame;	int newnum;	PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);	/* If we're not grabbing a frame right now and the other frame is */	/* ready to be grabbed into, then use it instead */	if (ov->curframe == -1) {		newnum = (framenum - 1 + OVFX2_NUMFRAMES) % OVFX2_NUMFRAMES;		if (ov->frame[newnum].grabstate == FRAME_READY)			framenum = newnum;	} else if (ov->frame[framenum].grabstate == FRAME_ERROR) {		PDEBUG(4, "restoring broken frame #%d", framenum);	} else		return 0;	frame = &ov->frame[framenum];	PDEBUG(4, "framenum = %d, width = %d, height = %d", framenum,	       frame->width, frame->height);	frame->bytes_read = 0;	frame->bytes_recvd = 0;	frame->grabstate = FRAME_GRABBING;	frame->scanstate = STATE_SCANNING;	ov->curframe = framenum;	/* Make sure it's not too big */	if (frame->width > ov->maxwidth)		frame->width = ov->maxwidth;	frame->width &= ~7L;		/* Multiple of 8 */	if (frame->height > ov->maxheight)		frame->height = ov->maxheight;	frame->height &= ~3L;		/* Multiple of 4 */	return 0;}/**************************************************************************** * * Buffer management * ***************************************************************************//* * - You must acquire buf_lock before entering this function. * - Because this code will free any non-null pointer, you must be sure to null *   them if you explicitly free them somewhere else! */static voidovfx2_do_dealloc(struct usb_ovfx2 *ov){	int i;	PDEBUG(4, "entered");	rvfree(ov->fbuf, OVFX2_NUMFRAMES	       * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));	ov->fbuf = NULL;	vfree(ov->rawfbuf);	ov->rawfbuf = NULL;	vfree(ov->tempfbuf);	ov->tempfbuf = NULL;	for (i = 0; i < OVFX2_NUMSBUF; i++) {		kfree(ov->sbuf[i].data);		ov->sbuf[i].data = NULL;	}	for (i = 0; i < OVFX2_NUMFRAMES; i++) {		ov->frame[i].data = NULL;		ov->frame[i].rawdata = NULL;		ov->frame[i].tempdata = NULL;	}	PDEBUG(4, "buffer memory deallocated");	ov->buf_state = BUF_NOT_ALLOCATED;	PDEBUG(4, "leaving");}static intovfx2_alloc(struct usb_ovfx2 *ov){	int i;	const int w = ov->maxwidth;	const int h = ov->maxheight;	const int data_bufsize = OVFX2_NUMFRAMES * MAX_DATA_SIZE(w, h);	const int raw_bufsize = OVFX2_NUMFRAMES * MAX_RAW_DATA_SIZE(w, h);	PDEBUG(4, "entered");	down(&ov->buf_lock);	if (ov->buf_state == BUF_ALLOCATED)		goto out;	ov->fbuf = rvmalloc(data_bufsize);	if (!ov->fbuf)		goto error;	ov->rawfbuf = vmalloc(raw_bufsize);	if (!ov->rawfbuf)		goto error;	memset(ov->rawfbuf, 0, raw_bufsize);	ov->tempfbuf = vmalloc(raw_bufsize);	if (!ov->tempfbuf)		goto error;	memset(ov->tempfbuf, 0, raw_bufsize);	for (i = 0; i < OVFX2_NUMSBUF; i++) {		ov->sbuf[i].data = kmalloc(OVFX2_BULK_SIZE, GFP_KERNEL);		if (!ov->sbuf[i].data)			goto error;		PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);	}	for (i = 0; i < OVFX2_NUMFRAMES; i++) {		ov->frame[i].data = ov->fbuf + i * MAX_DATA_SIZE(w, h);		ov->frame[i].rawdata = ov->rawfbuf		 + i * MAX_RAW_DATA_SIZE(w, h);		ov->frame[i].tempdata = ov->tempfbuf		 + i * MAX_RAW_DATA_SIZE(w, h);		PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);	}	ov->buf_state = BUF_ALLOCATED;out:	up(&ov->buf_lock);	PDEBUG(4, "leaving");	return 0;error:	ovfx2_do_dealloc(ov);	up(&ov->buf_lock);	PDEBUG(4, "errored");	return -ENOMEM;}static voidovfx2_dealloc(struct usb_ovfx2 *ov){	PDEBUG(4, "entered");	down(&ov->buf_lock);	ovfx2_do_dealloc(ov);	up(&ov->buf_lock);	PDEBUG(4, "leaving");}/**************************************************************************** * * V4L API * ***************************************************************************/#if defined(HAVE_V4L2)//static const struct v4l2_fmtdesc ovfx2_fmt_grey = {//	.description = "8 bpp, gray",//	.pixelformat = V4L2_PIX_FMT_GREY,//};static const struct v4l2_fmtdesc ovfx2_fmt_bgr24 = {	.description = "24 bpp, BGR, packed",	.pixelformat = V4L2_PIX_FMT_BGR24,};#endifstatic intovfx2_open(struct inode *inode, struct file *file){	struct video_device *vdev = video_devdata(file);	struct usb_ovfx2 *ov = video_get_drvdata(vdev);	int err, i;	PDEBUG(4, "opening");	down(&ov->lock);	err = -ENODEV;	if (!ov->dev)		goto out;	if (ov->sensor == CC_UNKNOWN) {		err("No sensor is detected yet");		goto out;	}	err = -EBUSY;	if (ov->user)		goto out;	ov->sub_flag = 0;	/* In case app doesn't set them... */	err = ovfx2_set_default_params(ov);	if (err < 0)		goto out;	/* Make sure frames are reset */	for (i = 0; i < OVFX2_NUMFRAMES; i++)		ov->frame[i].grabstate = FRAME_UNUSED;	err = ovfx2_alloc(ov);	if (err < 0)		goto out;	err = ovfx2_start_stream(ov);	if (err) {		ovfx2_dealloc(ov);		goto out;	}	ov->user++;	file->private_data = vdev;out:	up(&ov->lock);	return err;}static intovfx2_release(struct inode *inode, struct file *file){	struct video_device *vdev = file->private_data;	struct usb_ovfx2 *ov = video_get_drvdata(vdev);	PDEBUG(4, "close");	down(&ov->lock);	ov->user--;	ovfx2_stop_stream(ov);	ovfx2_dealloc(ov);	up(&ov->lock);	/* Device unplugged while open. Only a minimum of unregistration is done	 * here; the disconnect callback already did the rest. */	down(&ov_free_lock);	if (!ov->dev) {#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)		if (ov->vdev)			video_device_release(ov->vdev);#endif		kfree(ov);		ov = NULL;	}	up(&ov_free_lock);	file->private_data = NULL;	return 0;}/* Do not call this function directly! */static intovfx2_do_ioctl(struct inode *inode, struct file *file,			  unsigned int cmd, void *arg){	struct video_device *vdev = file->private_data;	struct usb_ovfx2 *ov = video_get_drvdata(vdev);#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)	switch (_IOC_TYPE(cmd)) {	case 'v':		PDEBUG(4, "ioctl 0x%x (v4l1, VIDIOC%s)", cmd,		       (_IOC_NR(cmd) < NUM_V4L1_IOCTLS) ?		       v4l1_ioctls[_IOC_NR(cmd)] : "???");		break;#  if defined(HAVE_V4L2)	case 'V':		PDEBUG(4, "ioctl 0x%x (v4l2, %s)", cmd,		       v4l2_ioctl_names[_IOC_NR(cmd)]);		break;#  endif	default:		PDEBUG(4, "ioctl 0x%x (?)", cmd);	}#else	if (debug >= 4)		v4l_print_ioctl("ovfx2", cmd);#endif	if (!ov->dev)		return -EIO;	switch (cmd) {	case VIDIOCGCAP:	{		struct video_capability *b = arg;		memset(b, 0, sizeof(struct video_capability));		sprintf(b->name, "OVFX2 USB Camera");		b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;		b->channels = 1;		b->maxwidth = ov->maxwidth;		b->maxheight = ov->maxheight;		b->minwidth = ov->minwidth;		b->minheight = ov->minheight;		return 0;	}	case VIDIOCGCHAN:	{		struct video_channel *v = arg;		if ((unsigned)(v->channel) > 0)			return -EINVAL;		v->norm = 0;		v->type = VIDEO_TYPE_CAMERA;		v->flags = 0;		v->tuners = 0;		sprintf(v->name, "%s", "Camera");		return 0;	}	case VIDIOCSCHAN:	{		struct video_channel *v = arg;		return (v->channel == 0) ? 0 : -EINVAL;	}	case VIDIOCGPICT:	{		struct video_picture *p = arg;		memset(p, 0, sizeof(struct video_picture));		if (sensor_get_picture(ov, p))			return -EIO;		/* Can we get these from frame[0]? -claudio? */		p->depth = ov->frame[0].depth;		p->palette = ov->frame[0].format;		return 0;	}	case VIDIOCSPICT:	{		struct video_picture *p = arg;		int i, rc;		if (!get_depth(p->palette))			return -EINVAL;		if (sensor_set_picture(ov, p))			return -EIO;		if (force_palette && p->palette != force_palette) {			info("SPICT: Palette rejected (%s)",			     symbolic(v4l1_plist, p->palette));			return -EINVAL;		}		// FIXME: Format should be independent of frames		if (p->palette != ov->frame[0].format) {			PDEBUG(4, "SPICT: Detected format change");			rc = ov51x_wait_frames_inactive(ov);			if (rc)				return rc;			mode_init_regs(ov, ov->frame[0].width,				ov->frame[0].height, p->palette, ov->sub_flag);		}		PDEBUG(4, "SPICT: Setting depth=%d, palette=%s",		       p->depth, symbolic(v4l1_plist, p->palette));		for (i = 0; i < OVFX2_NUMFRAMES; i++) {			ov->frame[i].depth = p->depth;			ov->frame[i].format = p->palette;		}		return 0;	}	case VIDIOCGCAPTURE:	{		int *vf = arg;		ov->sub_flag = *vf;		return 0;	}	case VIDIOCSCAPTURE:	{		struct video_capture *vc = arg;		if (vc->flags || vc->decimation)			return -EINVAL;		vc->x &= ~3L;		vc->y &= ~1L;		vc->y &= ~31L;		if (vc->width == 0)			vc->width = 32;		vc->height /= 16;		vc->height *= 16;		if (vc->height == 0)			vc->height = 16;		ov->subx = vc->x;		ov->suby = vc->y;		ov->subw = vc->width;		ov->subh = vc->height;		return 0;	}	case VIDIOCSWIN:	{		struct video_window *vw = arg;		int i, rc;		PDEBUG(4, "Set window: %dx%d", vw->width, vw->height);

⌨️ 快捷键说明

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