videodev.c

来自「omap3 linux 2.6 用nocc去除了冗余代码」· C语言 代码 · 共 2,112 行 · 第 1/4 页

C
2,112
字号
		break;	}	return cmd;}/* * Obsolete usercopy function - Should be removed soon */intvideo_usercopy(struct inode *inode, struct file *file,	       unsigned int cmd, unsigned long arg,	       int (*func)(struct inode *inode, struct file *file,			   unsigned int cmd, void *arg)){	char	sbuf[128];	void    *mbuf = NULL;	void	*parg = NULL;	int	err  = -EINVAL;	int     is_ext_ctrl;	size_t  ctrls_size = 0;	void __user *user_ptr = NULL;	cmd = video_fix_command(cmd);	is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||		       cmd == VIDIOC_TRY_EXT_CTRLS);	/*  Copy arguments into temp kernel buffer  */	switch (_IOC_DIR(cmd)) {	case _IOC_NONE:		parg = NULL;		break;	case _IOC_READ:	case _IOC_WRITE:	case (_IOC_WRITE | _IOC_READ):		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {			parg = sbuf;		} else {			/* too big to allocate from stack */			mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);			if (NULL == mbuf)				return -ENOMEM;			parg = mbuf;		}		err = -EFAULT;		if (_IOC_DIR(cmd) & _IOC_WRITE)			if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))				goto out;		break;	}	if (is_ext_ctrl) {		struct v4l2_ext_controls *p = parg;		/* In case of an error, tell the caller that it wasn't		   a specific control that caused it. */		p->error_idx = p->count;		user_ptr = (void __user *)p->controls;		if (p->count) {			ctrls_size = sizeof(struct v4l2_ext_control) * p->count;			/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */			mbuf = kmalloc(ctrls_size, GFP_KERNEL);			err = -ENOMEM;			if (NULL == mbuf)				goto out_ext_ctrl;			err = -EFAULT;			if (copy_from_user(mbuf, user_ptr, ctrls_size))				goto out_ext_ctrl;			p->controls = mbuf;		}	}	/* call driver */	err = func(inode, file, cmd, parg);	if (err == -ENOIOCTLCMD)		err = -EINVAL;	if (is_ext_ctrl) {		struct v4l2_ext_controls *p = parg;		p->controls = (void *)user_ptr;		if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))			err = -EFAULT;		goto out_ext_ctrl;	}	if (err < 0)		goto out;out_ext_ctrl:	/*  Copy results into user buffer  */	switch (_IOC_DIR(cmd))	{	case _IOC_READ:	case (_IOC_WRITE | _IOC_READ):		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))			err = -EFAULT;		break;	}out:	kfree(mbuf);	return err;}EXPORT_SYMBOL(video_usercopy);/* * open/release helper functions -- handle exclusive opens * Should be removed soon */int video_exclusive_open(struct inode *inode, struct file *file){	struct  video_device *vfl = video_devdata(file);	int retval = 0;	mutex_lock(&vfl->lock);	if (vfl->users) {		retval = -EBUSY;	} else {		vfl->users++;	}	mutex_unlock(&vfl->lock);	return retval;}EXPORT_SYMBOL(video_exclusive_open);int video_exclusive_release(struct inode *inode, struct file *file){	struct  video_device *vfl = video_devdata(file);	vfl->users--;	return 0;}EXPORT_SYMBOL(video_exclusive_release);static void dbgbuf(unsigned int cmd, struct video_device *vfd,					struct v4l2_buffer *p){	struct v4l2_timecode *tc=&p->timecode;	dbgarg (cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "		"bytesused=%d, flags=0x%08d, "		"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",			(p->timestamp.tv_sec/3600),			(int)(p->timestamp.tv_sec/60)%60,			(int)(p->timestamp.tv_sec%60),			p->timestamp.tv_usec,			p->index,			prt_names(p->type, v4l2_type_names),			p->bytesused, p->flags,			p->field, p->sequence,			prt_names(p->memory, v4l2_memory_names),			p->m.userptr, p->length);	dbgarg2 ("timecode= %02d:%02d:%02d type=%d, "		"flags=0x%08d, frames=%d, userbits=0x%08x\n",			tc->hours,tc->minutes,tc->seconds,			tc->type, tc->flags, tc->frames, *(__u32 *) tc->userbits);}static inline void dbgrect(struct video_device *vfd, char *s,							struct v4l2_rect *r){	dbgarg2 ("%sRect start at %dx%d, size= %dx%d\n", s, r->left, r->top,						r->width, r->height);};static inline void v4l_print_pix_fmt (struct video_device *vfd,						struct v4l2_pix_format *fmt){	dbgarg2 ("width=%d, height=%d, format=%c%c%c%c, field=%s, "		"bytesperline=%d sizeimage=%d, colorspace=%d\n",		fmt->width,fmt->height,		(fmt->pixelformat & 0xff),		(fmt->pixelformat >>  8) & 0xff,		(fmt->pixelformat >> 16) & 0xff,		(fmt->pixelformat >> 24) & 0xff,		prt_names(fmt->field, v4l2_field_names),		fmt->bytesperline, fmt->sizeimage, fmt->colorspace);};static int check_fmt (struct video_device *vfd, enum v4l2_buf_type type){	switch (type) {	case V4L2_BUF_TYPE_VIDEO_CAPTURE:		if (vfd->vidioc_try_fmt_cap)			return (0);		break;	case V4L2_BUF_TYPE_VIDEO_OVERLAY:		if (vfd->vidioc_try_fmt_overlay)			return (0);		break;	case V4L2_BUF_TYPE_VBI_CAPTURE:		if (vfd->vidioc_try_fmt_vbi)			return (0);		break;	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:		if (vfd->vidioc_try_fmt_vbi_output)			return (0);		break;	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:		if (vfd->vidioc_try_fmt_vbi_capture)			return (0);		break;	case V4L2_BUF_TYPE_VIDEO_OUTPUT:		if (vfd->vidioc_try_fmt_video_output)			return (0);		break;	case V4L2_BUF_TYPE_VBI_OUTPUT:		if (vfd->vidioc_try_fmt_vbi_output)			return (0);		break;	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:		if (vfd->vidioc_try_fmt_output_overlay)			return (0);		break;	case V4L2_BUF_TYPE_PRIVATE:		if (vfd->vidioc_try_fmt_type_private)			return (0);		break;	}	return (-EINVAL);}static int __video_do_ioctl(struct inode *inode, struct file *file,		unsigned int cmd, void *arg){	struct video_device *vfd = video_devdata(file);	void                 *fh = file->private_data;	int                  ret = -EINVAL;	if ( (vfd->debug & V4L2_DEBUG_IOCTL) &&				!(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {		v4l_print_ioctl(vfd->name, cmd);	}	/***********************************************************	 Handles calls to the obsoleted V4L1 API	 Due to the nature of VIDIOCGMBUF, each driver that supports	 V4L1 should implement its own handler for this ioctl.	 ***********************************************************/	/* --- streaming capture ------------------------------------- */	if (cmd == VIDIOCGMBUF) {		struct video_mbuf *p=arg;		memset(p, 0, sizeof(*p));		if (!vfd->vidiocgmbuf)			return ret;		ret=vfd->vidiocgmbuf(file, fh, p);		if (!ret)			dbgarg (cmd, "size=%d, frames=%d, offsets=0x%08lx\n",						p->size, p->frames,						(unsigned long)p->offsets);		return ret;	}	/********************************************************	 All other V4L1 calls are handled by v4l1_compat module.	 Those calls will be translated into V4L2 calls, and	 __video_do_ioctl will be called again, with one or more	 V4L2 ioctls.	 ********************************************************/	if (_IOC_TYPE(cmd)=='v')		return v4l_compat_translate_ioctl(inode,file,cmd,arg,						__video_do_ioctl);	switch(cmd) {	/* --- capabilities ------------------------------------------ */	case VIDIOC_QUERYCAP:	{		struct v4l2_capability *cap = (struct v4l2_capability*)arg;		memset(cap, 0, sizeof(*cap));		if (!vfd->vidioc_querycap)			break;		ret=vfd->vidioc_querycap(file, fh, cap);		if (!ret)			dbgarg (cmd, "driver=%s, card=%s, bus=%s, "					"version=0x%08x, "					"capabilities=0x%08x\n",					cap->driver,cap->card,cap->bus_info,					cap->version,					cap->capabilities);		break;	}	/* --- priority ------------------------------------------ */	case VIDIOC_G_PRIORITY:	{		enum v4l2_priority *p=arg;		if (!vfd->vidioc_g_priority)			break;		ret=vfd->vidioc_g_priority(file, fh, p);		if (!ret)			dbgarg(cmd, "priority is %d\n", *p);		break;	}	case VIDIOC_S_PRIORITY:	{		enum v4l2_priority *p=arg;		if (!vfd->vidioc_s_priority)			break;		dbgarg(cmd, "setting priority to %d\n", *p);		ret=vfd->vidioc_s_priority(file, fh, *p);		break;	}	/* --- capture ioctls ---------------------------------------- */	case VIDIOC_ENUM_FMT:	{		struct v4l2_fmtdesc *f = arg;		enum v4l2_buf_type type;		unsigned int index;		index = f->index;		type  = f->type;		memset(f,0,sizeof(*f));		f->index = index;		f->type  = type;		switch (type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			if (vfd->vidioc_enum_fmt_cap)				ret=vfd->vidioc_enum_fmt_cap(file, fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:			if (vfd->vidioc_enum_fmt_overlay)				ret=vfd->vidioc_enum_fmt_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_CAPTURE:			if (vfd->vidioc_enum_fmt_vbi)				ret=vfd->vidioc_enum_fmt_vbi(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:			if (vfd->vidioc_enum_fmt_vbi_output)				ret=vfd->vidioc_enum_fmt_vbi_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:			if (vfd->vidioc_enum_fmt_vbi_capture)				ret=vfd->vidioc_enum_fmt_vbi_capture(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT:			if (vfd->vidioc_enum_fmt_video_output)				ret=vfd->vidioc_enum_fmt_video_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_VBI_OUTPUT:			if (vfd->vidioc_enum_fmt_vbi_output)				ret=vfd->vidioc_enum_fmt_vbi_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:			if (vfd->vidioc_enum_fmt_output_overlay)				ret=vfd->vidioc_enum_fmt_output_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_PRIVATE:			if (vfd->vidioc_enum_fmt_type_private)				ret=vfd->vidioc_enum_fmt_type_private(file,								fh, f);			break;		}		if (!ret)			dbgarg (cmd, "index=%d, type=%d, flags=%d, "					"pixelformat=%c%c%c%c, description='%s'\n",					f->index, f->type, f->flags,					(f->pixelformat & 0xff),					(f->pixelformat >>  8) & 0xff,					(f->pixelformat >> 16) & 0xff,					(f->pixelformat >> 24) & 0xff,					f->description);		break;	}	case VIDIOC_G_FMT:	{		struct v4l2_format *f = (struct v4l2_format *)arg;		enum v4l2_buf_type type=f->type;		memset(&f->fmt.pix,0,sizeof(f->fmt.pix));		f->type=type;		/* FIXME: Should be one dump per type */		dbgarg (cmd, "type=%s\n", prt_names(type,					v4l2_type_names));		switch (type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			if (vfd->vidioc_g_fmt_cap)				ret=vfd->vidioc_g_fmt_cap(file, fh, f);			if (!ret)				v4l_print_pix_fmt(vfd,&f->fmt.pix);			break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:			if (vfd->vidioc_g_fmt_overlay)				ret=vfd->vidioc_g_fmt_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_CAPTURE:			if (vfd->vidioc_g_fmt_vbi)				ret=vfd->vidioc_g_fmt_vbi(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:			if (vfd->vidioc_g_fmt_vbi_output)				ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:			if (vfd->vidioc_g_fmt_vbi_capture)				ret=vfd->vidioc_g_fmt_vbi_capture(file, fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT:			if (vfd->vidioc_g_fmt_video_output)				ret=vfd->vidioc_g_fmt_video_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:			if (vfd->vidioc_g_fmt_output_overlay)				ret=vfd->vidioc_g_fmt_output_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_OUTPUT:			if (vfd->vidioc_g_fmt_vbi_output)				ret=vfd->vidioc_g_fmt_vbi_output(file, fh, f);			break;		case V4L2_BUF_TYPE_PRIVATE:			if (vfd->vidioc_g_fmt_type_private)				ret=vfd->vidioc_g_fmt_type_private(file,								fh, f);			break;		}		break;	}	case VIDIOC_S_FMT:	{		struct v4l2_format *f = (struct v4l2_format *)arg;		/* FIXME: Should be one dump per type */		dbgarg (cmd, "type=%s\n", prt_names(f->type,					v4l2_type_names));		switch (f->type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			v4l_print_pix_fmt(vfd,&f->fmt.pix);			if (vfd->vidioc_s_fmt_cap)				ret=vfd->vidioc_s_fmt_cap(file, fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:			if (vfd->vidioc_s_fmt_overlay)				ret=vfd->vidioc_s_fmt_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_CAPTURE:			if (vfd->vidioc_s_fmt_vbi)				ret=vfd->vidioc_s_fmt_vbi(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:			if (vfd->vidioc_s_fmt_vbi_output)				ret=vfd->vidioc_s_fmt_vbi_output(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:			if (vfd->vidioc_s_fmt_vbi_capture)				ret=vfd->vidioc_s_fmt_vbi_capture(file, fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT:			if (vfd->vidioc_s_fmt_video_output)				ret=vfd->vidioc_s_fmt_video_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:			if (vfd->vidioc_s_fmt_output_overlay)				ret=vfd->vidioc_s_fmt_output_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_OUTPUT:			if (vfd->vidioc_s_fmt_vbi_output)				ret=vfd->vidioc_s_fmt_vbi_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_PRIVATE:			if (vfd->vidioc_s_fmt_type_private)				ret=vfd->vidioc_s_fmt_type_private(file,								fh, f);			break;		}		break;	}	case VIDIOC_TRY_FMT:	{		struct v4l2_format *f = (struct v4l2_format *)arg;		/* FIXME: Should be one dump per type */		dbgarg (cmd, "type=%s\n", prt_names(f->type,						v4l2_type_names));		switch (f->type) {		case V4L2_BUF_TYPE_VIDEO_CAPTURE:			if (vfd->vidioc_try_fmt_cap)				ret=vfd->vidioc_try_fmt_cap(file, fh, f);			if (!ret)				v4l_print_pix_fmt(vfd,&f->fmt.pix);			break;		case V4L2_BUF_TYPE_VIDEO_OVERLAY:			if (vfd->vidioc_try_fmt_overlay)				ret=vfd->vidioc_try_fmt_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_CAPTURE:			if (vfd->vidioc_try_fmt_vbi)				ret=vfd->vidioc_try_fmt_vbi(file, fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:			if (vfd->vidioc_try_fmt_vbi_output)				ret=vfd->vidioc_try_fmt_vbi_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:			if (vfd->vidioc_try_fmt_vbi_capture)				ret=vfd->vidioc_try_fmt_vbi_capture(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT:			if (vfd->vidioc_try_fmt_video_output)				ret=vfd->vidioc_try_fmt_video_output(file,								fh, f);			break;		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:			if (vfd->vidioc_try_fmt_output_overlay)				ret=vfd->vidioc_try_fmt_output_overlay(file, fh, f);			break;		case V4L2_BUF_TYPE_VBI_OUTPUT:			if (vfd->vidioc_try_fmt_vbi_output)

⌨️ 快捷键说明

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