static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *up = compat_ptr(arg);
	void __user *up_native = NULL;
	void __user *aux_buf;
	u32 aux_space;
	int compatible_arg = 1;
	long err = 0;

	/* First, convert the command. */
	switch (cmd) {
	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_DQEVENT32: cmd = VIDIOC_DQEVENT; break;
	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
	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;
	case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
	case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
	case VIDIOC_G_EDID32: cmd = VIDIOC_G_EDID; break;
	case VIDIOC_S_EDID32: cmd = VIDIOC_S_EDID; break;
	}

	switch (cmd) {
	case VIDIOC_OVERLAY:
	case VIDIOC_STREAMON:
	case VIDIOC_STREAMOFF:
	case VIDIOC_S_INPUT:
	case VIDIOC_S_OUTPUT:
		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
		if (!err && assign_in_user((unsigned int __user *)up_native,
					   (compat_uint_t __user *)up))
			err = -EFAULT;
		compatible_arg = 0;
		break;

	case VIDIOC_G_INPUT:
	case VIDIOC_G_OUTPUT:
		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
		compatible_arg = 0;
		break;

	case VIDIOC_G_EDID:
	case VIDIOC_S_EDID:
		err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
		if (!err)
			err = get_v4l2_edid32(up_native, up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_FMT:
	case VIDIOC_S_FMT:
	case VIDIOC_TRY_FMT:
		err = bufsize_v4l2_format(up, &aux_space);
		if (!err)
			err = alloc_userspace(sizeof(struct v4l2_format),
					      aux_space, &up_native);
		if (!err) {
			aux_buf = up_native + sizeof(struct v4l2_format);
			err = get_v4l2_format32(up_native, up,
						aux_buf, aux_space);
		}
		compatible_arg = 0;
		break;

	case VIDIOC_CREATE_BUFS:
		err = bufsize_v4l2_create(up, &aux_space);
		if (!err)
			err = alloc_userspace(sizeof(struct v4l2_create_buffers),
					      aux_space, &up_native);
		if (!err) {
			aux_buf = up_native + sizeof(struct v4l2_create_buffers);
			err = get_v4l2_create32(up_native, up,
						aux_buf, aux_space);
		}
		compatible_arg = 0;
		break;

	case VIDIOC_PREPARE_BUF:
	case VIDIOC_QUERYBUF:
	case VIDIOC_QBUF:
	case VIDIOC_DQBUF:
		err = bufsize_v4l2_buffer(up, &aux_space);
		if (!err)
			err = alloc_userspace(sizeof(struct v4l2_buffer),
					      aux_space, &up_native);
		if (!err) {
			aux_buf = up_native + sizeof(struct v4l2_buffer);
			err = get_v4l2_buffer32(up_native, up,
						aux_buf, aux_space);
		}
		compatible_arg = 0;
		break;

	case VIDIOC_S_FBUF:
		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
				      &up_native);
		if (!err)
			err = get_v4l2_framebuffer32(up_native, up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_FBUF:
		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
				      &up_native);
		compatible_arg = 0;
		break;

	case VIDIOC_ENUMSTD:
		err = alloc_userspace(sizeof(struct v4l2_standard), 0,
				      &up_native);
		if (!err)
			err = get_v4l2_standard32(up_native, up);
		compatible_arg = 0;
		break;

	case VIDIOC_ENUMINPUT:
		err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
		if (!err)
			err = get_v4l2_input32(up_native, up);
		compatible_arg = 0;
		break;

	case VIDIOC_G_EXT_CTRLS:
	case VIDIOC_S_EXT_CTRLS:
	case VIDIOC_TRY_EXT_CTRLS:
		err = bufsize_v4l2_ext_controls(up, &aux_space);
		if (!err)
			err = alloc_userspace(sizeof(struct v4l2_ext_controls),
					      aux_space, &up_native);
		if (!err) {
			aux_buf = up_native + sizeof(struct v4l2_ext_controls);
			err = get_v4l2_ext_controls32(file, up_native, up,
						      aux_buf, aux_space);
		}
		compatible_arg = 0;
		break;
	case VIDIOC_DQEVENT:
		err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
		compatible_arg = 0;
		break;
	}
	if (err)
		return err;

	if (compatible_arg)
		err = native_ioctl(file, cmd, (unsigned long)up);
	else
		err = native_ioctl(file, cmd, (unsigned long)up_native);

	if (err == -ENOTTY)
		return err;

	/*
	 * 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(file, up_native, up))
			err = -EFAULT;
		break;
	case VIDIOC_S_EDID:
		if (put_v4l2_edid32(up_native, up))
			err = -EFAULT;
		break;
	}
	if (err)
		return err;

	switch (cmd) {
	case VIDIOC_S_INPUT:
	case VIDIOC_S_OUTPUT:
	case VIDIOC_G_INPUT:
	case VIDIOC_G_OUTPUT:
		if (assign_in_user((compat_uint_t __user *)up,
				   ((unsigned int __user *)up_native)))
			err = -EFAULT;
		break;

	case VIDIOC_G_FBUF:
		err = put_v4l2_framebuffer32(up_native, up);
		break;

	case VIDIOC_DQEVENT:
		err = put_v4l2_event32(up_native, up);
		break;

	case VIDIOC_G_EDID:
		err = put_v4l2_edid32(up_native, up);
		break;

	case VIDIOC_G_FMT:
	case VIDIOC_S_FMT:
	case VIDIOC_TRY_FMT:
		err = put_v4l2_format32(up_native, up);
		break;

	case VIDIOC_CREATE_BUFS:
		err = put_v4l2_create32(up_native, up);
		break;

	case VIDIOC_PREPARE_BUF:
	case VIDIOC_QUERYBUF:
	case VIDIOC_QBUF:
	case VIDIOC_DQBUF:
		err = put_v4l2_buffer32(up_native, up);
		break;

	case VIDIOC_ENUMSTD:
		err = put_v4l2_standard32(up_native, up);
		break;

	case VIDIOC_ENUMINPUT:
		err = put_v4l2_input32(up_native, up);
		break;
	}
	return err;
}