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

📄 v4l1-compat.c

📁 该代码是天敏电视卡天敏大师4的核心芯片在linux下面的驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	Video for Linux Two *	Backward Compatibility Layer * *	Support subroutines for providing V4L2 drivers with backward *	compatibility with applications using the old API. * *	This program is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License *	as published by the Free Software Foundation; either version *	2 of the License, or (at your option) any later version. * * Author:	Bill Dirks <bdirks@pacbell.net> *		et al. * */#ifndef __KERNEL__#define __KERNEL__#endif#include <linux/config.h>#include <linux/version.h>#include <linux/init.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/mm.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/slab.h>#include <linux/videodev.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/pgtable.h>#ifdef CONFIG_KMOD#include <linux/kmod.h>#endifstatic unsigned int debug  = 0;MODULE_PARM(debug,"i");MODULE_PARM_DESC(debug,"enable debug messages");MODULE_AUTHOR("Bill Dirks");MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");MODULE_LICENSE("GPL");#define dprintk(fmt, arg...)	if (debug) \	printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)/* *	I O C T L   T R A N S L A T I O N * *	From here on down is the code for translating the numerous *	ioctl commands from the old API to the new API. */static intget_v4l_control(struct inode            *inode,		struct file             *file,		int			cid,		v4l2_kioctl             drv){	struct v4l2_queryctrl	qctrl2;	struct v4l2_control	ctrl2;	int			err;	qctrl2.id = cid;	err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);	if (err < 0)		dprintk("VIDIOC_QUERYCTRL: %d\n",err);	if (err == 0 &&	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))	{		ctrl2.id = qctrl2.id;		err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);		if (err < 0) {			dprintk("VIDIOC_G_CTRL: %d\n",err);			return 0;		}		return ((ctrl2.value - qctrl2.minimum) * 65535			 + (qctrl2.maximum - qctrl2.minimum) / 2)			/ (qctrl2.maximum - qctrl2.minimum);	}	return 0;}static intset_v4l_control(struct inode            *inode,		struct file             *file,		int			cid,		int			value,		v4l2_kioctl             drv){	struct v4l2_queryctrl	qctrl2;	struct v4l2_control	ctrl2;	int			err;	qctrl2.id = cid;	err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);	if (err < 0)		dprintk("VIDIOC_QUERYCTRL: %d\n",err);	if (err == 0 &&	    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&	    !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))	{		if (value < 0)			value = 0;		if (value > 65535)			value = 65535;		if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)			value = 65535;		ctrl2.id = qctrl2.id;		ctrl2.value = 			(value * (qctrl2.maximum - qctrl2.minimum)			 + 32767)			/ 65535;		ctrl2.value += qctrl2.minimum;		err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);		if (err < 0)			dprintk("VIDIOC_S_CTRL: %d\n",err);	}	return 0;}/* ----------------------------------------------------------------- */static int palette2pixelformat[] = {	[VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,	[VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,	[VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,	[VIDEO_PALETTE_RGB24]   = V4L2_PIX_FMT_BGR24,	[VIDEO_PALETTE_RGB32]   = V4L2_PIX_FMT_BGR32,	/* yuv packed pixel */	[VIDEO_PALETTE_YUYV]    = V4L2_PIX_FMT_YUYV,	[VIDEO_PALETTE_YUV422]  = V4L2_PIX_FMT_YUYV,	[VIDEO_PALETTE_UYVY]    = V4L2_PIX_FMT_UYVY,	/* yuv planar */	[VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,	[VIDEO_PALETTE_YUV420]  = V4L2_PIX_FMT_YUV420,	[VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,	[VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,	[VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,};static unsigned intpalette_to_pixelformat(unsigned int palette){	if (palette < ARRAY_SIZE(palette2pixelformat))		return palette2pixelformat[palette];	else		return 0;}static unsigned intpixelformat_to_palette(int pixelformat){	int	palette = 0;	switch (pixelformat)	{	case V4L2_PIX_FMT_GREY:		palette = VIDEO_PALETTE_GREY;		break;	case V4L2_PIX_FMT_RGB555:		palette = VIDEO_PALETTE_RGB555;		break;	case V4L2_PIX_FMT_RGB565:		palette = VIDEO_PALETTE_RGB565;		break;	case V4L2_PIX_FMT_BGR24:		palette = VIDEO_PALETTE_RGB24;		break;	case V4L2_PIX_FMT_BGR32:		palette = VIDEO_PALETTE_RGB32;		break;	/* yuv packed pixel */	case V4L2_PIX_FMT_YUYV:		palette = VIDEO_PALETTE_YUYV;		break;	case V4L2_PIX_FMT_UYVY:		palette = VIDEO_PALETTE_UYVY;		break;	/* yuv planar */	case V4L2_PIX_FMT_YUV410:		palette = VIDEO_PALETTE_YUV420;		break;	case V4L2_PIX_FMT_YUV420:		palette = VIDEO_PALETTE_YUV420;		break;	case V4L2_PIX_FMT_YUV411P:		palette = VIDEO_PALETTE_YUV411P;		break;	case V4L2_PIX_FMT_YUV422P:		palette = VIDEO_PALETTE_YUV422P;		break;	}	return palette;}/* ----------------------------------------------------------------- */static int poll_one(struct file *file){	int retval = 1;	poll_table *table;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)	poll_table wait_table;	poll_initwait(&wait_table);	table = &wait_table;#else	struct poll_wqueues pwq;	poll_initwait(&pwq);	table = &pwq.pt;#endif	for (;;) {		int mask;		set_current_state(TASK_INTERRUPTIBLE);		mask = file->f_op->poll(file, table);		if (mask & POLLIN)			break;		table = NULL;		if (signal_pending(current)) {			retval = -ERESTARTSYS;			break;		}		schedule();	}	set_current_state(TASK_RUNNING);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48)	poll_freewait(&wait_table);#else	poll_freewait(&pwq);#endif	return retval;}static int count_inputs(struct inode         *inode,			struct file          *file,			v4l2_kioctl          drv){	struct v4l2_input input2;	int i;	for (i = 0;; i++) {		memset(&input2,0,sizeof(input2));		input2.index = i;		if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))			break;	}	return i;}static int check_size(struct inode         *inode,		      struct file          *file,		      v4l2_kioctl          drv,		      int *maxw, int *maxh){	struct v4l2_fmtdesc desc2;	struct v4l2_format  fmt2;	memset(&desc2,0,sizeof(desc2));	memset(&fmt2,0,sizeof(fmt2));		desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))		goto done;	fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;	fmt2.fmt.pix.width       = 10000;	fmt2.fmt.pix.height      = 10000;	fmt2.fmt.pix.pixelformat = desc2.pixelformat;	if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))		goto done;	*maxw = fmt2.fmt.pix.width;	*maxh = fmt2.fmt.pix.height; done:	return 0;}/* ----------------------------------------------------------------- *//* *	This function is exported. */intv4l_compat_translate_ioctl(struct inode         *inode,			   struct file		*file,			   int			cmd,			   void			*arg,			   v4l2_kioctl          drv){	struct v4l2_capability  *cap2 = NULL;	struct v4l2_format	*fmt2 = NULL;	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;	struct v4l2_framebuffer fbuf2;	struct v4l2_input	input2;	struct v4l2_tuner	tun2;	struct v4l2_standard	std2;	struct v4l2_frequency   freq2;	struct v4l2_audio	aud2;	struct v4l2_queryctrl	qctrl2;	struct v4l2_buffer	buf2;	v4l2_std_id    		sid;	int i, err = 0;	switch (cmd) {	case VIDIOCGCAP:	/* capability */	{		struct video_capability *cap = arg;		cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);		memset(cap, 0, sizeof(*cap));		memset(cap2, 0, sizeof(*cap2));		memset(&fbuf2, 0, sizeof(fbuf2));		err = drv(inode, file, VIDIOC_QUERYCAP, cap2);		if (err < 0) {			dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);			break;		}		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {			err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);			if (err < 0) {				dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);				memset(&fbuf2, 0, sizeof(fbuf2));			}			err = 0;		}		memcpy(cap->name, cap2->card, 		       min(sizeof(cap->name), sizeof(cap2->card)));		cap->name[sizeof(cap->name) - 1] = 0;		if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)			cap->type |= VID_TYPE_CAPTURE;		if (cap2->capabilities & V4L2_CAP_TUNER)			cap->type |= VID_TYPE_TUNER;		if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)			cap->type |= VID_TYPE_TELETEXT;		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)			cap->type |= VID_TYPE_OVERLAY;		if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)			cap->type |= VID_TYPE_CLIPPING;		cap->channels  = count_inputs(inode,file,drv);		check_size(inode,file,drv,			   &cap->maxwidth,&cap->maxheight);		cap->audios    =  0; /* FIXME */		cap->minwidth  = 48; /* FIXME */		cap->minheight = 32; /* FIXME */		break;	}	case VIDIOCGFBUF: /*  get frame buffer  */	{		struct video_buffer	*buffer = arg;		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);		if (err < 0) {			dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);			break;		}		buffer->base   = fbuf2.base;		buffer->height = fbuf2.fmt.height;		buffer->width  = fbuf2.fmt.width;		switch (fbuf2.fmt.pixelformat) {		case V4L2_PIX_FMT_RGB332:			buffer->depth = 8;				break;		case V4L2_PIX_FMT_RGB555:			buffer->depth = 15;			break;		case V4L2_PIX_FMT_RGB565:			buffer->depth = 16;			break;		case V4L2_PIX_FMT_BGR24:			buffer->depth = 24;			break;		case V4L2_PIX_FMT_BGR32:			buffer->depth = 32;			break;		default:			buffer->depth = 0;		}		if (0 != fbuf2.fmt.bytesperline)			buffer->bytesperline = fbuf2.fmt.bytesperline;		else {			buffer->bytesperline = 				(buffer->width * buffer->depth + 7) & 7;			buffer->bytesperline >>= 3;		}		break;	}	case VIDIOCSFBUF: /*  set frame buffer  */	{		struct video_buffer	*buffer = arg;		memset(&fbuf2, 0, sizeof(fbuf2));		fbuf2.base       = buffer->base;		fbuf2.fmt.height = buffer->height;		fbuf2.fmt.width  = buffer->width;		switch (buffer->depth) {		case 8:			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;			break;		case 15:			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;			break;		case 16:			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;			break;		case 24:			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;			break;		case 32:			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;			break;		}		fbuf2.fmt.bytesperline = buffer->bytesperline;		err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);		if (err < 0)			dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);		break;	}	case VIDIOCGWIN: /*  get window or capture dimensions  */	{		struct video_window	*win = arg;		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);		memset(win,0,sizeof(*win));		memset(fmt2,0,sizeof(*fmt2));		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;		err = drv(inode, file, VIDIOC_G_FMT, fmt2);		if (err < 0)			dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);		if (err == 0) {			win->x         = fmt2->fmt.win.w.left;			win->y         = fmt2->fmt.win.w.top;			win->width     = fmt2->fmt.win.w.width;			win->height    = fmt2->fmt.win.w.height;			win->chromakey = fmt2->fmt.win.chromakey;			win->clips     = NULL;			win->clipcount = 0;			break;		}		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		err = drv(inode, file, VIDIOC_G_FMT, fmt2);		if (err < 0) {			dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);			break;		}		win->x         = 0;		win->y         = 0;		win->width     = fmt2->fmt.pix.width;		win->height    = fmt2->fmt.pix.height;		win->chromakey = 0;		win->clips     = NULL;		win->clipcount = 0;		break;	}	case VIDIOCSWIN: /*  set window and/or capture dimensions  */	{		struct video_window	*win = arg;		int err1,err2;		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);		memset(fmt2,0,sizeof(*fmt2));		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);		err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);		if (err1 < 0)			dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);		if (err1 == 0) {			fmt2->fmt.pix.width  = win->width;			fmt2->fmt.pix.height = win->height;			fmt2->fmt.pix.field  = V4L2_FIELD_ANY;			fmt2->fmt.pix.bytesperline = 0;			err = drv(inode, file, VIDIOC_S_FMT, fmt2);			if (err < 0)				dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",					err);			win->width  = fmt2->fmt.pix.width;			win->height = fmt2->fmt.pix.height;		}		memset(fmt2,0,sizeof(*fmt2));		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;		fmt2->fmt.win.w.left    = win->x;		fmt2->fmt.win.w.top     = win->y;		fmt2->fmt.win.w.width   = win->width;		fmt2->fmt.win.w.height  = win->height;		fmt2->fmt.win.chromakey = win->chromakey;		fmt2->fmt.win.clips     = (void *)win->clips;		fmt2->fmt.win.clipcount = win->clipcount;		err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);		if (err2 < 0)			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);		if (err1 != 0 && err2 != 0)			err = err1;		break;	}	case VIDIOCCAPTURE: /*  turn on/off preview  */	{		int *on = arg;		if (0 == *on) {			/* dirty hack time.  But v4l1 has no STREAMOFF			 * equivalent in the API, and this one at			 * least comes close ... */			drv(inode, file, VIDIOC_STREAMOFF, &captype);		}		err = drv(inode, file, VIDIOC_OVERLAY, arg);

⌨️ 快捷键说明

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