/*
 * Copyright (C) 2013 Google, Inc.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
 * may be copied, distributed, and modified under those terms.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/uaccess.h>
#include <video/adf.h>

#include "adf_fops.h"
#include "adf_fops32.h"

long adf_compat_post_config(struct file *file,
		struct adf_post_config32 __user *arg)
{
	struct adf_post_config32 cfg32;
	struct adf_post_config __user *cfg;
	int ret;

	if (copy_from_user(&cfg32, arg, sizeof(cfg32)))
		return -EFAULT;

	cfg = compat_alloc_user_space(sizeof(*cfg));
	if (!access_ok(VERIFY_WRITE, cfg, sizeof(*cfg)))
		return -EFAULT;

	if (put_user(cfg32.n_interfaces, &cfg->n_interfaces) ||
			put_user(compat_ptr(cfg32.interfaces),
					&cfg->interfaces) ||
			put_user(cfg32.n_bufs, &cfg->n_bufs) ||
			put_user(compat_ptr(cfg32.bufs), &cfg->bufs) ||
			put_user(cfg32.custom_data_size,
					&cfg->custom_data_size) ||
			put_user(compat_ptr(cfg32.custom_data),
					&cfg->custom_data))
		return -EFAULT;

	ret = adf_file_ioctl(file, ADF_POST_CONFIG, (unsigned long)cfg);
	if (ret < 0)
		return ret;

	if (copy_in_user(&arg->complete_fence, &cfg->complete_fence,
			sizeof(cfg->complete_fence)))
		return -EFAULT;

	return 0;
}

long adf_compat_get_device_data(struct file *file,
		struct adf_device_data32 __user *arg)
{
	struct adf_device_data32 data32;
	struct adf_device_data __user *data;
	int ret;

	if (copy_from_user(&data32, arg, sizeof(data32)))
		return -EFAULT;

	data = compat_alloc_user_space(sizeof(*data));
	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
		return -EFAULT;

	if (put_user(data32.n_attachments, &data->n_attachments) ||
			put_user(compat_ptr(data32.attachments),
					&data->attachments) ||
			put_user(data32.n_allowed_attachments,
					&data->n_allowed_attachments) ||
			put_user(compat_ptr(data32.allowed_attachments),
					&data->allowed_attachments) ||
			put_user(data32.custom_data_size,
					&data->custom_data_size) ||
			put_user(compat_ptr(data32.custom_data),
					&data->custom_data))
		return -EFAULT;

	ret = adf_file_ioctl(file, ADF_GET_DEVICE_DATA, (unsigned long)data);
	if (ret < 0)
		return ret;

	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
			copy_in_user(&arg->n_attachments, &data->n_attachments,
					sizeof(arg->n_attachments)) ||
			copy_in_user(&arg->n_allowed_attachments,
					&data->n_allowed_attachments,
					sizeof(arg->n_allowed_attachments)) ||
			copy_in_user(&arg->custom_data_size,
					&data->custom_data_size,
					sizeof(arg->custom_data_size)))
		return -EFAULT;

	return 0;
}

long adf_compat_get_interface_data(struct file *file,
		struct adf_interface_data32 __user *arg)
{
	struct adf_interface_data32 data32;
	struct adf_interface_data __user *data;
	int ret;

	if (copy_from_user(&data32, arg, sizeof(data32)))
		return -EFAULT;

	data = compat_alloc_user_space(sizeof(*data));
	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
		return -EFAULT;

	if (put_user(data32.n_available_modes, &data->n_available_modes) ||
			put_user(compat_ptr(data32.available_modes),
					&data->available_modes) ||
			put_user(data32.custom_data_size,
					&data->custom_data_size) ||
			put_user(compat_ptr(data32.custom_data),
					&data->custom_data))
		return -EFAULT;

	ret = adf_file_ioctl(file, ADF_GET_INTERFACE_DATA, (unsigned long)data);
	if (ret < 0)
		return ret;

	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
			copy_in_user(&arg->type, &data->type,
					sizeof(arg->type)) ||
			copy_in_user(&arg->id, &data->id, sizeof(arg->id)) ||
			copy_in_user(&arg->flags, &data->flags,
					sizeof(arg->flags)) ||
			copy_in_user(&arg->dpms_state, &data->dpms_state,
					sizeof(arg->dpms_state)) ||
			copy_in_user(&arg->hotplug_detect,
					&data->hotplug_detect,
					sizeof(arg->hotplug_detect)) ||
			copy_in_user(&arg->width_mm, &data->width_mm,
					sizeof(arg->width_mm)) ||
			copy_in_user(&arg->height_mm, &data->height_mm,
					sizeof(arg->height_mm)) ||
			copy_in_user(&arg->current_mode, &data->current_mode,
					sizeof(arg->current_mode)) ||
			copy_in_user(&arg->n_available_modes,
					&data->n_available_modes,
					sizeof(arg->n_available_modes)) ||
			copy_in_user(&arg->custom_data_size,
					&data->custom_data_size,
					sizeof(arg->custom_data_size)))
		return -EFAULT;

	return 0;
}

long adf_compat_get_overlay_engine_data(struct file *file,
		struct adf_overlay_engine_data32 __user *arg)
{
	struct adf_overlay_engine_data32 data32;
	struct adf_overlay_engine_data __user *data;
	int ret;

	if (copy_from_user(&data32, arg, sizeof(data32)))
		return -EFAULT;

	data = compat_alloc_user_space(sizeof(*data));
	if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
		return -EFAULT;

	if (put_user(data32.n_supported_formats, &data->n_supported_formats) ||
			put_user(compat_ptr(data32.supported_formats),
					&data->supported_formats) ||
			put_user(data32.custom_data_size,
					&data->custom_data_size) ||
			put_user(compat_ptr(data32.custom_data),
					&data->custom_data))
		return -EFAULT;

	ret = adf_file_ioctl(file, ADF_GET_OVERLAY_ENGINE_DATA,
			(unsigned long)data);
	if (ret < 0)
		return ret;

	if (copy_in_user(arg->name, data->name, sizeof(arg->name)) ||
			copy_in_user(&arg->n_supported_formats,
					&data->n_supported_formats,
					sizeof(arg->n_supported_formats)) ||
			copy_in_user(&arg->custom_data_size,
					&data->custom_data_size,
					sizeof(arg->custom_data_size)))
		return -EFAULT;

	return 0;
}

long adf_file_compat_ioctl(struct file *file, unsigned int cmd,
		unsigned long arg)
{
	switch (cmd) {
	case ADF_POST_CONFIG32:
		return adf_compat_post_config(file, compat_ptr(arg));

	case ADF_GET_DEVICE_DATA32:
		return adf_compat_get_device_data(file, compat_ptr(arg));

	case ADF_GET_INTERFACE_DATA32:
		return adf_compat_get_interface_data(file, compat_ptr(arg));

	case ADF_GET_OVERLAY_ENGINE_DATA32:
		return adf_compat_get_overlay_engine_data(file,
				compat_ptr(arg));

	default:
		return adf_file_ioctl(file, cmd, arg);
	}
}
