Beispiel #1
0
static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    union {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
        struct video_tuner vt;
        struct video_buffer vb;
        struct video_window vw;
        struct video_code vc;
        struct video_audio va;
#endif
        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) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
    case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break;
    case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break;
    case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break;
    case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break;
    case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break;
    case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break;
    case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break;
    case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break;
#endif
    case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break;
    case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break;
    case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break;
    case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break;
    case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break;
    case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break;
    case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break;
    case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break;
    case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break;
    case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break;
    case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
    case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
    case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break;
    case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break;
    case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break;
    case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break;
    };

    switch(cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
    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:
#endif
    case VIDIOC_S_INPUT:
    case VIDIOC_OVERLAY:
    case VIDIOC_STREAMON:
    case VIDIOC_STREAMOFF:
        err = get_user(karg.vx, (u32 __user *)up);
        compatible_arg = 1;
        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;

#ifdef CONFIG_VIDEO_V4L1_COMPAT
    case VIDIOCGWIN:
    case VIDIOCGFBUF:
    case VIDIOCGFREQ:
#endif
    case VIDIOC_G_FBUF:
    case VIDIOC_G_INPUT:
        compatible_arg = 0;
        break;
#ifdef CONFIG_VIDEO_V4L1_COMPAT
    case VIDIOCSMICROCODE:
        err = microcode32(&karg.vc, up);
        compatible_arg = 0;
        break;
#endif
    };
    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) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
        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;

#endif
        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;

#ifdef CONFIG_VIDEO_V4L1_COMPAT
        case VIDIOCGFREQ:
#endif
        case VIDIOC_G_INPUT:
            err = put_user(((u32)karg.vx), (u32 __user *)up);
            break;
        };
    }
out:
    return err;
}
static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	union {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
		struct video_tuner vt;
		struct video_buffer vb;
		struct video_window vw;
		struct video_code vc;
		struct video_audio va;
#endif
		struct v4l2_format v2f;
		struct v4l2_buffer v2b;
		struct v4l2_framebuffer v2fb;
		struct v4l2_input v2i;
		struct v4l2_standard v2s;
		struct v4l2_ext_controls v2ecs;
		unsigned long vx;
		int vi;
	} karg;
	void __user *up = compat_ptr(arg);
	int compatible_arg = 1;
	long err = 0;

	/* First, convert the command. */
	switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
	case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
	case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
#endif
	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_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
	case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
	case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
	case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
#ifdef __OLD_VIDIOC_
	case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
#endif
	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
	}

	switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
	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 VIDIOCSWIN:
		err = get_video_window32(&karg.vw, up);
		compatible_arg = 0;
		break;

	case VIDIOCGWIN:
	case VIDIOCGFBUF:
	case VIDIOCGFREQ:
		compatible_arg = 0;
		break;

	case VIDIOCSMICROCODE:
		err = get_microcode32(&karg.vc, up);
		compatible_arg = 0;
		break;

	case VIDIOCSFREQ:
		err = get_user(karg.vx, (u32 __user *)up);
		compatible_arg = 0;
		break;

	case VIDIOCCAPTURE:
	case VIDIOCSYNC:
	case VIDIOCSWRITEMODE:
#endif
	case VIDIOC_OVERLAY:
	case VIDIOC_STREAMON:
	case VIDIOC_STREAMOFF:
	case VIDIOC_S_INPUT:
	case VIDIOC_S_OUTPUT:
		err = get_user(karg.vi, (s32 __user *)up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_INPUT:
	case VIDIOC_G_OUTPUT:
		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_S_FBUF:
		err = get_v4l2_framebuffer32(&karg.v2fb, up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_FBUF:
		compatible_arg = 0;
		break;

	case VIDIOC_ENUMSTD:
		err = get_v4l2_standard32(&karg.v2s, up);
		compatible_arg = 0;
		break;

	case VIDIOC_ENUMINPUT:
		err = get_v4l2_input32(&karg.v2i, up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_EXT_CTRLS:
	case VIDIOC_S_EXT_CTRLS:
	case VIDIOC_TRY_EXT_CTRLS:
		err = get_v4l2_ext_controls32(&karg.v2ecs, up);
		compatible_arg = 0;
		break;
	}
	if (err)
		return err;

	if (compatible_arg)
		err = native_ioctl(file, cmd, (unsigned long)up);
	else {
		mm_segment_t old_fs = get_fs();

		set_fs(KERNEL_DS);
		err = native_ioctl(file, cmd, (unsigned long)&karg);
		set_fs(old_fs);
	}

	/* Special case: even after an error we need to put the
	   results back for these ioctls since the error_idx will
	   contain information on which control failed. */
	switch (cmd) {
	case VIDIOC_G_EXT_CTRLS:
	case VIDIOC_S_EXT_CTRLS:
	case VIDIOC_TRY_EXT_CTRLS:
		if (put_v4l2_ext_controls32(&karg.v2ecs, up))
			err = -EFAULT;
		break;
	}
	if (err)
		return err;

	switch (cmd) {
#ifdef CONFIG_VIDEO_V4L1_COMPAT
	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 VIDIOCGFREQ:
		err = put_user(((u32)karg.vx), (u32 __user *)up);
		break;
#endif
	case VIDIOC_S_INPUT:
	case VIDIOC_S_OUTPUT:
	case VIDIOC_G_INPUT:
	case VIDIOC_G_OUTPUT:
		err = put_user(((s32)karg.vi), (s32 __user *)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_standard32(&karg.v2s, up);
		break;

	case VIDIOC_ENUMINPUT:
		err = put_v4l2_input32(&karg.v2i, up);
		break;
	}
	return err;
}