compat_ioctl32.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 873 行 · 第 1/2 页

C
873
字号
static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up){	u32 tmp;	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||		get_user(tmp, &up->base) ||		get_user(kp->capability, &up->capability) ||		get_user(kp->flags, &up->flags))			return -EFAULT;	kp->base = compat_ptr(tmp);	get_v4l2_pix_format(&kp->fmt, &up->fmt);	return 0;}static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up){	u32 tmp = (u32)((unsigned long)kp->base);	if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||		put_user(tmp, &up->base) ||		put_user(kp->capability, &up->capability) ||		put_user(kp->flags, &up->flags))			return -EFAULT;	put_v4l2_pix_format(&kp->fmt, &up->fmt);	return 0;}static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up){	if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))		return -EFAULT;	return 0;}static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up){	if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))		return -EFAULT;	return 0;}static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up){	if (copy_from_user(kp, up, sizeof(struct v4l2_input)))		return -EFAULT;	return 0;}static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up){	if (copy_to_user(up, kp, sizeof(struct v4l2_input)))		return -EFAULT;	return 0;}#define VIDIOCGTUNER32		_IOWR('v',4, struct video_tuner32)#define VIDIOCSTUNER32		_IOW('v',5, struct video_tuner32)#define VIDIOCGWIN32		_IOR('v',9, struct video_window32)#define VIDIOCSWIN32		_IOW('v',10, struct video_window32)#define VIDIOCGFBUF32		_IOR('v',11, struct video_buffer32)#define VIDIOCSFBUF32		_IOW('v',12, struct video_buffer32)#define VIDIOCGFREQ32		_IOR('v',14, u32)#define VIDIOCSFREQ32		_IOW('v',15, u32)/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */#define VIDIOC_ENUMINPUT32	VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)#define VIDIOC_G_FMT32		_IOWR ('V',  4, struct v4l2_format32)#define VIDIOC_S_FMT32		_IOWR ('V',  5, struct v4l2_format32)#define VIDIOC_QUERYBUF32	_IOWR ('V',  9, struct v4l2_buffer32)#define VIDIOC_G_FBUF32		_IOR  ('V', 10, struct v4l2_framebuffer32)#define VIDIOC_S_FBUF32		_IOW  ('V', 11, struct v4l2_framebuffer32)/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */#define VIDIOC_OVERLAY32	_IOWR ('V', 14, compat_int_t)#define VIDIOC_QBUF32		_IOWR ('V', 15, struct v4l2_buffer32)#define VIDIOC_DQBUF32		_IOWR ('V', 17, struct v4l2_buffer32)#define VIDIOC_STREAMON32	_IOW  ('V', 18, compat_int_t)#define VIDIOC_STREAMOFF32	_IOW  ('V', 19, compat_int_t)#define VIDIOC_ENUMSTD32	_IOWR ('V', 25, struct v4l2_standard32)/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */#define VIDIOC_S_CTRL32		_IOW  ('V', 28, struct v4l2_control)#define VIDIOC_G_INPUT32	_IOR  ('V', 38, compat_int_t)#define VIDIOC_S_INPUT32	_IOWR ('V', 39, compat_int_t)#define VIDIOC_TRY_FMT32      	_IOWR ('V', 64, struct v4l2_format32)enum {	MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)};static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg){	struct video_window32 __user *up = compat_ptr(arg);	struct video_window __user *vw;	struct video_clip __user *p;	int nclips;	u32 n;	if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))		return -EFAULT;	if (get_user(nclips, &up->clipcount))		return -EFAULT;	/* Peculiar interface... */	if (nclips < 0)		nclips = VIDEO_CLIPMAP_SIZE;	if (nclips > MaxClips)		return -ENOMEM;	vw = compat_alloc_user_space(sizeof(struct video_window) +				    nclips * sizeof(struct video_clip));	p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;	if (get_user(n, &up->x) || put_user(n, &vw->x) ||	    get_user(n, &up->y) || put_user(n, &vw->y) ||	    get_user(n, &up->width) || put_user(n, &vw->width) ||	    get_user(n, &up->height) || put_user(n, &vw->height) ||	    get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||	    get_user(n, &up->flags) || put_user(n, &vw->flags) ||	    get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||	    get_user(n, &up->clips) || put_user(p, &vw->clips))		return -EFAULT;	if (nclips) {		struct video_clip32 __user *u = compat_ptr(n);		int i;		if (!u)			return -EINVAL;		for (i = 0; i < nclips; i++, u++, p++) {			s32 v;			if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) ||			    !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) ||			    get_user(v, &u->x) ||			    put_user(v, &p->x) ||			    get_user(v, &u->y) ||			    put_user(v, &p->y) ||			    get_user(v, &u->width) ||			    put_user(v, &p->width) ||			    get_user(v, &u->height) ||			    put_user(v, &p->height) ||			    put_user(NULL, &p->next))				return -EFAULT;		}	}	return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);}static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg){	union {		struct video_tuner vt;		struct video_buffer vb;		struct video_window vw;		struct v4l2_format v2f;		struct v4l2_buffer v2b;		struct v4l2_framebuffer v2fb;		struct v4l2_standard v2s;		struct v4l2_input v2i;		struct v4l2_tuner v2t;		unsigned long vx;	} karg;	void __user *up = compat_ptr(arg);	int compatible_arg = 1;	int err = 0;	int realcmd = cmd;	/* First, convert the command. */	switch(cmd) {	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;	case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;	case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;	case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;	case VIDIOC_S_CTRL32: cmd = VIDIOC_S_CTRL; break;	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;	};	switch(cmd) {	case VIDIOCSTUNER:	case VIDIOCGTUNER:		err = get_video_tuner32(&karg.vt, up);		compatible_arg = 0;		break;	case VIDIOCSFBUF:		err = get_video_buffer32(&karg.vb, up);		compatible_arg = 0;		break;	case VIDIOCSFREQ:	case VIDIOC_S_INPUT:	case VIDIOC_OVERLAY:	case VIDIOC_STREAMON:	case VIDIOC_STREAMOFF:		err = get_user(karg.vx, (u32 __user *)up);		compatible_arg = 0;		break;	case VIDIOC_S_FBUF:		err = get_v4l2_framebuffer32(&karg.v2fb, up);		compatible_arg = 0;		break;	case VIDIOC_G_FMT:	case VIDIOC_S_FMT:	case VIDIOC_TRY_FMT:		err = get_v4l2_format32(&karg.v2f, up);		compatible_arg = 0;		break;	case VIDIOC_QUERYBUF:	case VIDIOC_QBUF:	case VIDIOC_DQBUF:		err = get_v4l2_buffer32(&karg.v2b, up);		compatible_arg = 0;		break;	case VIDIOC_ENUMSTD:		err = get_v4l2_standard(&karg.v2s, up);		compatible_arg = 0;		break;	case VIDIOC_ENUMSTD32:		err = get_v4l2_standard32(&karg.v2s, up);		compatible_arg = 0;		break;	case VIDIOC_ENUMINPUT:		err = get_v4l2_input(&karg.v2i, up);		compatible_arg = 0;		break;	case VIDIOC_ENUMINPUT32:		err = get_v4l2_input32(&karg.v2i, up);		compatible_arg = 0;		break;	case VIDIOC_G_TUNER:	case VIDIOC_S_TUNER:		err = get_v4l2_tuner(&karg.v2t, up);		compatible_arg = 0;		break;	case VIDIOCGWIN:	case VIDIOCGFBUF:	case VIDIOCGFREQ:	case VIDIOC_G_FBUF:	case VIDIOC_G_INPUT:		compatible_arg = 0;	};	if(err)		goto out;	if(compatible_arg)		err = native_ioctl(file, realcmd, (unsigned long)up);	else {		mm_segment_t old_fs = get_fs();		set_fs(KERNEL_DS);		err = native_ioctl(file, realcmd, (unsigned long)&karg);		set_fs(old_fs);	}	if(err == 0) {		switch(cmd) {		case VIDIOCGTUNER:			err = put_video_tuner32(&karg.vt, up);			break;		case VIDIOCGWIN:			err = put_video_window32(&karg.vw, up);			break;		case VIDIOCGFBUF:			err = put_video_buffer32(&karg.vb, up);			break;		case VIDIOC_G_FBUF:			err = put_v4l2_framebuffer32(&karg.v2fb, up);			break;		case VIDIOC_G_FMT:		case VIDIOC_S_FMT:		case VIDIOC_TRY_FMT:			err = put_v4l2_format32(&karg.v2f, up);			break;		case VIDIOC_QUERYBUF:		case VIDIOC_QBUF:		case VIDIOC_DQBUF:			err = put_v4l2_buffer32(&karg.v2b, up);			break;		case VIDIOC_ENUMSTD:			err = put_v4l2_standard(&karg.v2s, up);			break;		case VIDIOC_ENUMSTD32:			err = put_v4l2_standard32(&karg.v2s, up);			break;		case VIDIOC_G_TUNER:		case VIDIOC_S_TUNER:			err = put_v4l2_tuner(&karg.v2t, up);			break;		case VIDIOC_ENUMINPUT:			err = put_v4l2_input(&karg.v2i, up);			break;		case VIDIOC_ENUMINPUT32:			err = put_v4l2_input32(&karg.v2i, up);			break;		case VIDIOCGFREQ:		case VIDIOC_G_INPUT:			err = put_user(((u32)karg.vx), (u32 __user *)up);			break;		};	}out:	return err;}long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg){	int ret = -ENOIOCTLCMD;	if (!file->f_op->ioctl)		return ret;	switch (cmd) {	case VIDIOCSWIN32:		ret = do_set_window(file, cmd, arg);		break;	case VIDIOCGTUNER32:	case VIDIOCSTUNER32:	case VIDIOCGWIN32:	case VIDIOCGFBUF32:	case VIDIOCSFBUF32:	case VIDIOCGFREQ32:	case VIDIOCSFREQ32:	case VIDIOC_QUERYCAP:	case VIDIOC_ENUM_FMT:	case VIDIOC_G_FMT32:	case VIDIOC_S_FMT32:	case VIDIOC_REQBUFS:	case VIDIOC_QUERYBUF32:	case VIDIOC_G_FBUF32:	case VIDIOC_S_FBUF32:	case VIDIOC_OVERLAY32:	case VIDIOC_QBUF32:	case VIDIOC_DQBUF32:	case VIDIOC_STREAMON32:	case VIDIOC_STREAMOFF32:	case VIDIOC_G_PARM:	case VIDIOC_G_STD:	case VIDIOC_S_STD:	case VIDIOC_G_TUNER:	case VIDIOC_S_TUNER:	case VIDIOC_ENUMSTD:	case VIDIOC_ENUMSTD32:	case VIDIOC_ENUMINPUT:	case VIDIOC_ENUMINPUT32:	case VIDIOC_G_CTRL:	case VIDIOC_S_CTRL32:	case VIDIOC_QUERYCTRL:	case VIDIOC_G_INPUT32:	case VIDIOC_S_INPUT32:	case VIDIOC_TRY_FMT32:		ret = do_video_ioctl(file, cmd, arg);		break;	/* Little v, the video4linux ioctls (conflict?) */	case VIDIOCGCAP:	case VIDIOCGCHAN:	case VIDIOCSCHAN:	case VIDIOCGPICT:	case VIDIOCSPICT:	case VIDIOCCAPTURE:	case VIDIOCKEY:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:	case VIDIOCSYNC:	case VIDIOCMCAPTURE:	case VIDIOCGMBUF:	case VIDIOCGUNIT:	case VIDIOCGCAPTURE:	case VIDIOCSCAPTURE:	/* BTTV specific... */	case _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]):	case _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]):	case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):	case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */	case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):	case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):	case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):	case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):		ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));		break;	default:		v4l_print_ioctl("compat_ioctl32", cmd);	}	return ret;}#elselong v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg){	return -ENOIOCTLCMD;}#endifEXPORT_SYMBOL_GPL(v4l_compat_ioctl32);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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