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

📄 v4l2.c

📁 pxa270下的摄像头mtd91111的驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
}#endif	/* MVL-CEE *//* * *      M E M O R Y   M A P P I N G * */static struct stream_buffer *mmap_stream_buffer_from_offset (struct capture_device *dev,				unsigned long offset){	int i;	offset = offset * PAGE_SIZE;	for (i = 0; i < MAX_CAPTURE_BUFFERS; ++i)		if (offset == dev->stream_buf[i].vidbuf.offset)			return &dev->stream_buf[i];	return NULL;}static intmmap_request_buffers (struct capture_device *dev,		      struct v4l2_requestbuffers *req){	int i;	u32 buflen;	u32 type;	if (dev->stream_buffers_mapped)		return 0;	/* can't make requests if buffers are mapped */	if (req->count < 1)		req->count = 1;	if (req->count > MAX_CAPTURE_BUFFERS)		req->count = MAX_CAPTURE_BUFFERS;	type = V4L2_BUF_TYPE_CAPTURE;	dev->stream_contig_map = 0;	if (req->type & V4L2_BUF_REQ_CONTIG) {		dev->stream_contig_map = 1;		req->type = type | V4L2_BUF_REQ_CONTIG;		/* note: _REQ_CONTIG is only used in v4l2_requestbuffers */	}	/*  The buffer length needs to be a multiple of the page size  */	buflen = (dev->clientfmt.sizeimage + PAGE_SIZE - 1)		& ~(PAGE_SIZE - 1);	//dbg("Granting %d buffers\n",req->count);	/*  Now initialize the buffer structures. Don't allocate the */	/*  buffers until they're mapped. */	for (i = 0; i < req->count; ++i) {		dev->stream_buf[i].requested = 1;		dev->stream_buf[i].vidbuf.index = i;		dev->stream_buf[i].vidbuf.type = type;		/* offset must be unique for each buffer, and a multiple */		/* of PAGE_SIZE on 2.4.x  */		dev->stream_buf[i].vidbuf.offset = PAGE_SIZE * (i + 1);		dev->stream_buf[i].vidbuf.length = buflen;		dev->stream_buf[i].vidbuf.bytesused = 0;		dev->stream_buf[i].vidbuf.flags = 0;		dev->stream_buf[i].vidbuf.timestamp = 0;		dev->stream_buf[i].vidbuf.sequence = 0;		memset (&dev->stream_buf[i].vidbuf.timecode, 0,			sizeof (struct v4l2_timecode));	}	for (i = req->count; i < MAX_CAPTURE_BUFFERS; ++i)		dev->stream_buf[i].requested = 0;	dev->stream_buffers_requested = req->count;	return 1;}static voidmmap_unrequest_buffers (struct capture_device *dev){	int i;	if (dev->stream_buffers_requested == 0 || dev->stream_buffers_mapped)		return;	for (i = 0; i < MAX_CAPTURE_BUFFERS; ++i)		dev->stream_buf[i].requested = 0;	dev->stream_buffers_requested = 0;}static voidmmap_vma_open (struct vm_area_struct *vma){	struct capture_device *dev = capture_device_from_file (vma->vm_file);	struct stream_buffer *buf;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	if (dev == NULL)		return;	buf = mmap_stream_buffer_from_offset (dev, vma->vm_pgoff);	if (dev->stream_contig_map)		buf = &dev->stream_buf[0];	++buf->vma_refcount;	//dbg("vma_open called\n");	//MOD_INC_USE_COUNT;}static voidmmap_vma_close (struct vm_area_struct *vma){	struct capture_device *dev = capture_device_from_file (vma->vm_file);	struct stream_buffer *buf =		mmap_stream_buffer_from_offset (dev, vma->vm_pgoff);	int i, n = 1;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	if (dev->stream_contig_map) {	/*     Unmap all the buffers in one stroke  */		n = dev->stream_buffers_mapped;		buf = &dev->stream_buf[0];	}	--buf->vma_refcount;	if (buf->vma_refcount > 0)		return;	for (i = 0; i < n; ++i) {		if (dev->streaming) {			//dbg("Warning- munmap() called while streaming\n");			capture_streamoff (dev, buf->vidbuf.type);		}		v4l2_q_yank_node (&dev->stream_q_capture, &buf->qnode);		v4l2_q_yank_node (&dev->stream_q_done, &buf->qnode);		if (buf->vaddress != NULL && i == 0)			vfree (buf->vaddress);		buf->vaddress = NULL;		if (buf->dma_list)			free_page ((unsigned long) buf->dma_list);		buf->dma_list = NULL;		buf->vidbuf.flags = 0;		//dbg("Buffer %d deallocated\n",(int)vma->vm_pgoff);		++buf;		if (dev->stream_buffers_mapped > 0)			--dev->stream_buffers_mapped;	}	//MOD_DEC_USE_COUNT;}static struct page *mmap_vma_nopage (struct vm_area_struct *vma, unsigned long address, int write){	struct capture_device *dev;	struct stream_buffer *buf;	unsigned long offset_into_buffer;	struct page *page;	int n = 1;	dev = capture_device_from_file (vma->vm_file);	if (dev == NULL)		return 0;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	if (dev->stream_contig_map) {		buf = &dev->stream_buf[0];		n = dev->stream_buffers_requested;	} else		buf = mmap_stream_buffer_from_offset (dev, vma->vm_pgoff);	if (buf == NULL)		return 0;	offset_into_buffer = address - vma->vm_start;	if (offset_into_buffer >= buf->vidbuf.length * n) {		err ("Attempt to read past end of mmap() buffer\n");		return 0;	}	page = v4l2_vmalloc_to_page (buf->vaddress + offset_into_buffer);	if (page == 0)		return 0;	atomic_inc (&page->count);	return page;}static struct vm_operations_struct capture_vma_operations = {	mmap_vma_open, mmap_vma_close, mmap_vma_nopage,};/* * *      V 4 L 2   I N T E R F A C E * */static intv4l2_open (struct v4l2_device *v, int flags, void **idptr){	struct capture_device *dev = (struct capture_device *) v;	int i, n;	int cap;	int retcode;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	for (i = 0, n = -1, cap = 0; i < MAX_OPENS; ++i) {		if (!dev->open_data[i].isopen)			n = i;	/* available open_data structure */		else if (!dev->open_data[i].noncapturing)			cap = 1;	/* another open is already capturing */	}	if (n == -1) {		/* No available open_data structures */		//dbg("No more opens on this device\n");		return -EBUSY;	}	if (flags & O_NONCAP)	/*  Non-capturing open */		dev->open_data[n].noncapturing = 1;	else if (cap) {		//dbg("No more capturing opens on this device\n");		return -EBUSY;	} else {		dev->open_data[n].noncapturing = 0;		/*  Keep track of whether there is a capturing open  */		++dev->capturing_opens;		dev->perf.frames = 0;		dev->perf.framesdropped = 0;		dev->perf.bytesout = 0;	}	//MOD_INC_USE_COUNT;	++dev->open_count;	dev->open_data[n].isopen = 1;	dev->open_data[n].dev = dev;	*idptr = &dev->open_data[n];	if (dev->open_count == 1) {		if (dev->preview) {			// If preview mode is on then we will refrain			// from any furthur device initialization since			// it isn't needed and actually will disrupt the			// automatic preview operation that the driver			// is in the process of doing. Recall that apps			// can open() the video device, turn on preview,			// and then close() it; preview continues. Sometime			// later they may re-open() the device and we don't			// want that disrupting the on-going preview			// processing.			return 0;		}		if ((retcode = dev->camif->open ())) {			dev->open_count = 0;			dev->open_data[n].isopen = 0;			return retcode;		}				dev->ready_to_capture = 0;	/* benchmark changes parameters! */		dev->capture_completed = 0;		dev->capture_started = 0;		v4l2_q_init (&dev->stream_q_capture);		v4l2_q_init (&dev->stream_q_done);	}	//dbg("Open succeeded\n");	/* frame counter for test images only */	if (!dev->open_data[n].noncapturing)		dev->h = dev->m = dev->s = dev->f = 0;	return 0;}static voidv4l2_close (void *id){	struct device_open *o = (struct device_open *) id;	struct capture_device *dev = o->dev;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	if (!o->noncapturing) {		--dev->capturing_opens;		//dbg("Close\n");	}	o->isopen = 0;	--dev->open_count;	if (dev->preview) {		// If we have been placed into preview mode then		// we want to keep that going even if the app		// closes the video device. We expect sometime		// later the app, or some app, will open the		// video device and turn off preview when it		// desires. This video driver handles the		// preview operation and all the app needs to		// do is briefly open() us and turn on or		// off the preview mode and then, if desired,		// close() us.		return;	}	// shut things down.	if (dev->open_count == 0) {		capture_close (dev);		dev->camif->close ();	}	//MOD_DEC_USE_COUNT;}static longv4l2_write (void *id, const char *buf, unsigned long count, int noblock){	//dbg("Write() not handled\n");	return -EINVAL;}/*  The arguments are already copied into kernel memory, so don't use    copy_from_user() or copy_to_user() on arg.  */static intv4l2_ioctl (void *id, unsigned int cmd, void *arg){	struct device_open *o = (struct device_open *) id;	struct capture_device *dev = o->dev;#ifdef CONFIG_CEE  /* MVL-CEE */	wait_event(dev->suspend_wq, dev->suspended == 0);#endif /* MVL-CEE */	switch (cmd) {	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *b = arg;		strcpy (b->name, dev->v.name);		b->type = V4L2_TYPE_CAPTURE;		b->flags = V4L2_FLAG_READ |			V4L2_FLAG_STREAMING |			V4L2_FLAG_PREVIEW | V4L2_FLAG_SELECT;		b->inputs = dev->videc.num_inputs;		b->outputs = 0;		b->audios = 0;		b->maxwidth = MAX_WIDTH;		b->maxheight = MAX_HEIGHT;		b->minwidth = MIN_WIDTH;		b->minheight = MIN_HEIGHT;		b->maxframerate = 30;		return 0;	}	case VIDIOC_ENUM_PIXFMT:	{		struct v4l2_fmtdesc *f = arg;		if (f->index < 0 || f->index >= NUM_CAPFMT)			return -EINVAL;		*f = capfmt[f->index];		return 0;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *fmt = arg;		if (fmt->type != V4L2_BUF_TYPE_CAPTURE) {			//dbg("G_FMT wrong buffer type %d\n",fmt->type);			return -EINVAL;		}		fmt->fmt.pix = dev->clientfmt;		return 0;	}	case VIDIOC_S_FMT:	{		struct v4l2_format *fmt = arg;		if (o->noncapturing) {			//dbg("S_FMT illegal in non-capturing open\n");			return -EPERM;		}		if (fmt->type != V4L2_BUF_TYPE_CAPTURE) {			//dbg("S_FMT wrong buffer type %d\n",fmt->type);			return -EINVAL;		}		dev->clientfmt = fmt->fmt.pix;		capture_abort (dev);		if (capture_new_format (dev))			return -EINVAL;		if (dev->streaming)			capture_stream_start (dev);		else if (dev->preview)			capture_grab_frame (dev);		fmt->fmt.pix = dev->clientfmt;		return 0;	}	case VIDIOC_G_COMP:		return -EINVAL;	case VIDIOC_S_COMP:		return -EINVAL;	case VIDIOC_REQBUFS:	{		struct v4l2_requestbuffers *req = arg;		if (o->noncapturing) {			//dbg("REQBUFS illegal in non-capturing open\n");			return -EPERM;		}		if (dev->stream_buffers_mapped) {			//dbg("Can't request buffers if buffers are "			//         "already mapped\n");			return -EPERM;		}		mmap_unrequest_buffers (dev);		capture_begin (dev);		if (!mmap_request_buffers (dev, req))			return -EINVAL;		return 0;	}	case VIDIOC_QUERYBUF:	{		struct v4l2_buffer *buf = arg;		int i;		if (o->noncapturing) {			//dbg("QUERYBUF illegal in non-capturing open\n");			return -EPERM;		}		i = buf->index;		if (i < 0 || i >= MAX_CAPTURE_BUFFERS ||		    !dev->stream_buf[i].requested ||		    (buf->type & V4L2_BUF_TYPE_field) !=		    (dev->stream_buf[i].vidbuf.		     type & V4L2_BUF_TYPE_field)) {			//dbg("QUERYBUF bad parameter\n");			return -EINVAL;		}		*buf = dev->stream_buf[i].vidbuf;		return 0;	}	case VIDIOC_QBUF:	{		struct v4l2_buffer *buf = arg;		if (o->noncapturing) {			//dbg("QBUF illegal in non-capturing open\n");			return -EPERM;		}		if (!dev->stream_buffers_mapped) {			//dbg("QBUF no buffers are mapped\n");			return -EINVAL;		}		if (!capture_queuebuffer (dev, buf))			return -EINVAL;		return 0;	}	case VIDIOC_DQBUF:	{		struct v4l2_buffer *buf = arg;		if (o->noncapturing) {			//dbg("DQBUF illegal in non-capturing open\n");			return -EPERM;		}		if (!capture_dequeuebuffer (dev, buf))			return -EINVAL;		return 0;	}	case VIDIOC_STREAMON:	{		__u32 *type = arg;		if (o->noncapturing) {			//dbg("STREAMON illegal in non-capturing open\n");			return -EPERM;		}		if (!capture_streamon (dev, *type))			return -EINVAL;		return 0;	}	case VIDIOC_STREAMOFF:	{		__u32 *type = arg;		if (o->noncapturing) {			//dbg("STREAMOFF illegal in non-capturing open\n");			return -EPERM;		}		capture_streamoff (dev, *type);		return 0;	}	case VIDIOC_ENUM_FBUFFMT:		return -EINVAL;	case VIDIOC_G_FBUF:		return -EINVAL;	case VIDIOC_S_FBUF:		return -EINVAL;	case VIDIOC_G_WIN:		return -EINVAL;	case VIDIOC_S_WIN:		return -EINVAL;	case VIDIOC_PREVIEW:	{		int *on = (unsigned int *) arg;		dbg ("VIDIOC_PREVIEW %d\n", *on);	// *revisit-skranz* temp.		if (!dev->preview && (*on == 1)) {			// It is "off" now but we want it "on", so...			/*			 * schedule the framebuffer info updater to run			 * (it has to run under keventd).			 */			dev->fbinfo_valid = 0;			fbinfo_tsk_q_entry.routine =				update_fbinfo_task;			fbinfo_tsk_q_entry.data = (void *) dev;			schedule_task (&fbinfo_tsk_q_entry);			interruptible_sleep_on (&dev->fbinfo_wait);			if (signal_pending (current))				return -ERESTARTSYS;			dev->preview = 1;			capture_grab_frame (dev);			if (!dev->ready_to_capture) {				dbg ("ioctl(..,VIDIOC_PREVIEW,...); Can't grab frames!\n");				return -EINVAL;			}		} else {			if (dev->preview && (*on == 0)) {				// It is "on" now but we want it "off", so...				capture_abort (dev);				dev->ready_to_capture = 0;				dev->preview = 0;			}		}		return 0;	}	case VIDIOC_G_PERF:	{		memcpy (arg, &dev->perf, sizeof (dev->perf));		return 0;	}	case VIDIOC_G_INPUT:	{		memcpy (arg, &dev->input, sizeof (dev->input));		return 0;	}	case VIDIOC_S_INPUT:	{		int input = *(int *) arg;		if (input < 0 || input >= dev->videc.num_inputs) {			//dbg("Input out of range %d\n", input);			return -EINVAL;		}		if (input != dev->input) {			dev->SwitchInputs = 1;			dev->input = input;			set_video_input (dev, input);		}

⌨️ 快捷键说明

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