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

📄 uvc_v4l2.c

📁 linux camera下的uvc driver驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		uvc_ctrl_begin(video);		for (i = 0; i < ctrls->count; ++ctrl, ++i) {			ret = uvc_ctrl_get(video, ctrl);			if (ret < 0) {				uvc_ctrl_rollback(video);				ctrls->error_idx = i;				return ret;			}		}		ctrls->error_idx = 0;		ret = uvc_ctrl_rollback(video);	}		break;	case VIDIOC_S_EXT_CTRLS:	case VIDIOC_TRY_EXT_CTRLS:	{		struct v4l2_ext_controls *ctrls = (struct v4l2_ext_controls*)arg;		struct v4l2_ext_control *ctrl = ctrls->controls;		unsigned int i;		ret = uvc_ctrl_begin(video);		if (ret < 0)			return ret;		for (i = 0; i < ctrls->count; ++ctrl, ++i) {			ret = uvc_ctrl_set(video, ctrl);			if (ret < 0) {				uvc_ctrl_rollback(video);				ctrls->error_idx = i;				return ret;			}		}		ctrls->error_idx = 0;		if (cmd == VIDIOC_S_EXT_CTRLS)			ret = uvc_ctrl_commit(video);		else			ret = uvc_ctrl_rollback(video);	}		break;	/* Get, Set & Enum input */	case VIDIOC_ENUMINPUT:	{		const struct uvc_entity *selector = video->selector;		struct v4l2_input *input = arg;		struct uvc_entity *iterm = NULL;		u32 index = input->index;		int pin = 0;		if (selector == NULL) {			if (index != 0)				return -EINVAL;			iterm = list_first_entry(&video->iterms,					struct uvc_entity, chain);			pin = iterm->id;		} else if (pin < selector->selector.bNrInPins) {			pin = selector->selector.baSourceID[index];			list_for_each_entry(iterm, video->iterms.next, chain) {				if (iterm->id == pin)					break;			}		}		if (iterm == NULL || iterm->id != pin)			return -EINVAL;		memset(input, 0, sizeof *input);		input->index = index;		strncpy(input->name, iterm->name, sizeof input->name);		if (UVC_ENTITY_TYPE(iterm) == ITT_CAMERA)			input->type = V4L2_INPUT_TYPE_CAMERA;	}		break;	case VIDIOC_G_INPUT:	{		u8 input;		if (video->selector == NULL) {			*(int*)arg = 0;			break;		}		ret = uvc_query_ctrl(video->dev, GET_CUR, video->selector->id,			video->dev->intfnum, SU_INPUT_SELECT_CONTROL,			&input, 1);		if (ret < 0)			return ret;		*(int*)arg = input - 1;	}		break;	case VIDIOC_S_INPUT:	{		u8 input = *(u32*)arg + 1;		if ((ret = uvc_acquire_privileges(handle)) < 0)			return ret;		if (video->selector == NULL) {			if (input != 1)				return -EINVAL;			break;		}		if (input > video->selector->selector.bNrInPins)			return -EINVAL;		return uvc_query_ctrl(video->dev, SET_CUR, video->selector->id,			video->dev->intfnum, SU_INPUT_SELECT_CONTROL,			&input, 1);	}	/* Try, Get, Set & Enum format */	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *fmt = arg;		struct uvc_format *format;		if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||		    fmt->index >= video->streaming->nformats)			return -EINVAL;		format = &video->streaming->format[fmt->index];		fmt->flags = 0;		if (format->flags & UVC_FMT_FLAG_COMPRESSED)			fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;		strncpy(fmt->description, format->name,			sizeof fmt->description);		fmt->description[sizeof fmt->description - 1] = 0;		fmt->pixelformat = format->fcc;	}		break;	case VIDIOC_TRY_FMT:	{		struct uvc_streaming_control probe;		if ((ret = uvc_acquire_privileges(handle)) < 0)			return ret;		return uvc_v4l2_try_format(video, (struct v4l2_format*)arg,						&probe, NULL, NULL);	}	case VIDIOC_S_FMT:		if ((ret = uvc_acquire_privileges(handle)) < 0)			return ret;		return uvc_v4l2_set_format(video, (struct v4l2_format*)arg);	case VIDIOC_G_FMT:		return uvc_v4l2_get_format(video, (struct v4l2_format*)arg);	/* Frame size enumeration */	case VIDIOC_ENUM_FRAMESIZES:	{		struct v4l2_frmsizeenum *fsize = arg;		struct uvc_format *format = NULL;		struct uvc_frame *frame;		int i;		/* Look for the given pixel format */		for (i = 0; i < video->streaming->nformats; i++) {			if (video->streaming->format[i].fcc == fsize->pixel_format) {				format = &video->streaming->format[i];				break;			}		}		if (format == NULL)			return -EINVAL;		if (fsize->index >= format->nframes)			return -EINVAL;		frame = &format->frame[fsize->index];		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;		fsize->discrete.width = frame->wWidth;		fsize->discrete.height = frame->wHeight;	}		break;	/* Frame interval enumeration */	case VIDIOC_ENUM_FRAMEINTERVALS:	{		struct v4l2_frmivalenum *fival = arg;		struct uvc_format *format;		struct uvc_frame *frame = NULL;		int i, j;		/* Look for the given pixel format and frame size */		for (i = 0; i < video->streaming->nformats; i++) {			if (video->streaming->format[i].fcc == fival->pixel_format) {				format = &video->streaming->format[i];				for (j = 0; j < format->nframes; j++) {					if (format->frame[j].wWidth == fival->width &&					    format->frame[j].wHeight == fival->height) {						frame = &format->frame[j];						break;					}				}				break;	/* Each format should occur only once. */			}		}		if (frame == NULL)			return -EINVAL;		if (frame->bFrameIntervalType) {			if (fival->index >= frame->bFrameIntervalType)				return -EINVAL;			fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;			fival->discrete.numerator = frame->dwFrameInterval[fival->index];			fival->discrete.denominator = 10000000;			uvc_simplify_fraction(&fival->discrete.numerator,					&fival->discrete.denominator, 8, 333);		} else {			fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;			fival->stepwise.min.numerator = frame->dwFrameInterval[0];			fival->stepwise.min.denominator = 10000000;			fival->stepwise.max.numerator = frame->dwFrameInterval[1];			fival->stepwise.max.denominator = 10000000;			fival->stepwise.step.numerator = frame->dwFrameInterval[2];			fival->stepwise.step.denominator = 10000000;			uvc_simplify_fraction(&fival->stepwise.min.numerator,					&fival->stepwise.min.denominator, 8, 333);			uvc_simplify_fraction(&fival->stepwise.max.numerator,					&fival->stepwise.max.denominator, 8, 333);			uvc_simplify_fraction(&fival->stepwise.step.numerator,					&fival->stepwise.step.denominator, 8, 333);		}	}		break;	/* Get & Set streaming parameters */	case VIDIOC_G_PARM:		return uvc_v4l2_get_streamparm(video, (struct v4l2_streamparm*)arg);	case VIDIOC_S_PARM:		if ((ret = uvc_acquire_privileges(handle)) < 0)			return ret;		return uvc_v4l2_set_streamparm(video, (struct v4l2_streamparm*)arg);	/* Cropping and scaling */	case VIDIOC_CROPCAP:	{		struct v4l2_cropcap *ccap = arg;		struct uvc_frame *frame = video->streaming->cur_frame;		if (ccap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		ccap->bounds.left = 0;		ccap->bounds.top = 0;		ccap->bounds.width = frame->wWidth;		ccap->bounds.height = frame->wHeight;		ccap->defrect = ccap->bounds;		ccap->pixelaspect.numerator = 1;		ccap->pixelaspect.denominator = 1;	}		break;	case VIDIOC_G_CROP:	case VIDIOC_S_CROP:		return -EINVAL;	/* Buffers & streaming */	case VIDIOC_REQBUFS:	{		struct v4l2_requestbuffers *rb = arg;		unsigned int bufsize = video->streaming->ctrl.dwMaxVideoFrameSize;		if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||		    rb->memory != V4L2_MEMORY_MMAP)			return -EINVAL;		if ((ret = uvc_acquire_privileges(handle)) < 0)			return ret;		if ((ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize)) < 0)			return ret;		rb->count = ret;		ret = 0;	}		break;	case VIDIOC_QUERYBUF:	{		struct v4l2_buffer *buf = arg;		if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (!uvc_has_privileges(handle))			return -EBUSY;		return uvc_query_buffer(&video->queue, buf);	}	case VIDIOC_QBUF:		if (!uvc_has_privileges(handle))			return -EBUSY;		return uvc_queue_buffer(&video->queue,			(struct v4l2_buffer*)arg);	case VIDIOC_DQBUF:		if (!uvc_has_privileges(handle))			return -EBUSY;		return uvc_dequeue_buffer(&video->queue,			(struct v4l2_buffer*)arg, file->f_flags & O_NONBLOCK);	case VIDIOC_STREAMON:	{		int *type = arg;		if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (!uvc_has_privileges(handle))			return -EBUSY;		if ((ret = uvc_video_enable(video, 1)) < 0)			return ret;	}		break;	case VIDIOC_STREAMOFF:	{		int *type = arg;		if (*type != V4L2_BUF_TYPE_VIDEO_CAPTURE)			return -EINVAL;		if (!uvc_has_privileges(handle))			return -EBUSY;		return uvc_video_enable(video, 0);	}	/* Analog video standards make no sense for digital cameras. */	case VIDIOC_ENUMSTD:	case VIDIOC_QUERYSTD:	case VIDIOC_G_STD:	case VIDIOC_S_STD:	case VIDIOC_OVERLAY:	case VIDIOC_ENUMAUDIO:	case VIDIOC_ENUMAUDOUT:	case VIDIOC_ENUMOUTPUT:		uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);		return -EINVAL;	/* Dynamic controls. */	case UVCIOC_CTRL_ADD:	{		struct uvc_xu_control_info *xinfo = arg;		struct uvc_control_info *info;		info = kmalloc(sizeof *info, GFP_KERNEL);		if (info == NULL)			return -ENOMEM;		memcpy(info->entity, xinfo->entity, sizeof info->entity);		info->index = xinfo->index;		info->selector = xinfo->selector;		info->size = xinfo->size;		info->flags = xinfo->flags;		info->flags |= UVC_CONTROL_GET_MIN | UVC_CONTROL_GET_MAX |				UVC_CONTROL_GET_RES | UVC_CONTROL_GET_DEF;		ret = uvc_ctrl_add_info(info);		if (ret < 0)			kfree(info);	}		break;	case UVCIOC_CTRL_MAP:	{		struct uvc_xu_control_mapping *xmap = arg;		struct uvc_control_mapping *map;		map = kmalloc(sizeof *map, GFP_KERNEL);		if (map == NULL)			return -ENOMEM;		map->id = xmap->id;		memcpy(map->name, xmap->name, sizeof map->name);		memcpy(map->entity, xmap->entity, sizeof map->entity);		map->selector = xmap->selector;		map->size = xmap->size;		map->offset = xmap->offset;		map->v4l2_type = xmap->v4l2_type;		map->data_type = xmap->data_type;		ret = uvc_ctrl_add_mapping(map);		if (ret < 0)			kfree(map);	}		break;	case UVCIOC_CTRL_GET:		return uvc_xu_ctrl_query(video, (struct uvc_xu_control*)arg, 0);	case UVCIOC_CTRL_SET:		return uvc_xu_ctrl_query(video, (struct uvc_xu_control*)arg, 1);	default:		if ((ret = v4l_compat_translate_ioctl(inode, file, cmd, arg,			uvc_v4l2_do_ioctl)) == -ENOIOCTLCMD)			uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);		return ret;	}	return ret;}static int uvc_v4l2_ioctl(struct inode *inode, struct file *file,		     unsigned int cmd, unsigned long arg){	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_ioctl\n");	return video_usercopy(inode, file, cmd, arg, uvc_v4l2_do_ioctl);}static ssize_t uvc_v4l2_read(struct file *file, char __user *data,		    size_t count, loff_t *ppos){	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n");	return -ENODEV;}/* * VMA operations. */static void uvc_vm_open(struct vm_area_struct *vma){	struct uvc_buffer *buffer = vma->vm_private_data;	buffer->vma_use_count++;}static void uvc_vm_close(struct vm_area_struct *vma){	struct uvc_buffer *buffer = vma->vm_private_data;	buffer->vma_use_count--;}static struct vm_operations_struct uvc_vm_ops = {	.open		= uvc_vm_open,	.close		= uvc_vm_close,};static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma){	struct video_device *vdev = video_devdata(file);	struct uvc_video_device *video = video_get_drvdata(vdev);	struct uvc_buffer *buffer = NULL;	struct page *page;	unsigned long addr, start, size;	unsigned int i;	int ret = 0;	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");	start = vma->vm_start;	size = vma->vm_end - vma->vm_start;	mutex_lock(&video->queue.mutex);	for (i = 0; i < video->queue.count; ++i) {		if ((video->queue.buffer[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) {			buffer = &video->queue.buffer[i];			break;		}	}	if (buffer == NULL || size != video->queue.buf_size) {		ret = -EINVAL;		goto done;	}	/*	 * VM_IO marks the area as being an mmaped region for I/O to a	 * device. It also prevents the region from being core dumped.	 */	vma->vm_flags |= VM_IO;	addr = (unsigned long)video->queue.mem + buffer->buf.m.offset;	while (size > 0) {		page = vmalloc_to_page((void*)addr);		if ((ret = vm_insert_page(vma, start, page)) < 0)			goto done;		start += PAGE_SIZE;		addr += PAGE_SIZE;		size -= PAGE_SIZE;	}	vma->vm_ops = &uvc_vm_ops;	vma->vm_private_data = buffer;	uvc_vm_open(vma);done:	mutex_unlock(&video->queue.mutex);	return ret;}static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait){	struct video_device *vdev = video_devdata(file);	struct uvc_video_device *video = video_get_drvdata(vdev);	uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n");	return uvc_queue_poll(&video->queue, file, wait);}struct file_operations uvc_fops = {	.owner		= THIS_MODULE,	.open		= uvc_v4l2_open,	.release	= uvc_v4l2_release,	.ioctl		= uvc_v4l2_ioctl,#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,15)	.compat_ioctl	= v4l_compat_ioctl32,#endif	.llseek		= no_llseek,	.read		= uvc_v4l2_read,	.mmap		= uvc_v4l2_mmap,	.poll		= uvc_v4l2_poll,};

⌨️ 快捷键说明

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