| /* |
| * 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); |
| } |
| } |