12d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale/* 22d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * 32bit compatibility wrappers for the input subsystem. 32d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * 42d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik 52d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * 62d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * This program is free software; you can redistribute it and/or modify it 72d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * under the terms of the GNU General Public License version 2 as published by 82d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * the Free Software Foundation. 92d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale */ 102d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1115d0580f20f5d3f997e3823bfe39daa3d521a99dPaul Gortmaker#include <linux/export.h> 122d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#include <asm/uaccess.h> 132d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#include "input-compat.h" 142d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 152d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#ifdef CONFIG_COMPAT 162d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 172d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_from_user(const char __user *buffer, 182d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct input_event *event) 192d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 20f930a7a0f4c87bf3ee731383421ebf3164009ee7H. J. Lu if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) { 212d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct input_event_compat compat_event; 222d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 232d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(&compat_event, buffer, 242d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale sizeof(struct input_event_compat))) 252d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 262d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 272d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale event->time.tv_sec = compat_event.time.tv_sec; 282d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale event->time.tv_usec = compat_event.time.tv_usec; 292d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale event->type = compat_event.type; 302d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale event->code = compat_event.code; 312d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale event->value = compat_event.value; 322d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 332d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } else { 342d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(event, buffer, sizeof(struct input_event))) 352d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 362d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } 372d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 382d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 392d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 402d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 412d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_to_user(char __user *buffer, 422d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale const struct input_event *event) 432d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 44f930a7a0f4c87bf3ee731383421ebf3164009ee7H. J. Lu if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) { 452d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct input_event_compat compat_event; 462d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 472d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_event.time.tv_sec = event->time.tv_sec; 482d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_event.time.tv_usec = event->time.tv_usec; 492d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_event.type = event->type; 502d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_event.code = event->code; 512d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_event.value = event->value; 522d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 532d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_to_user(buffer, &compat_event, 542d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale sizeof(struct input_event_compat))) 552d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 562d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 572d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } else { 582d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_to_user(buffer, event, sizeof(struct input_event))) 592d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 602d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } 612d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 622d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 632d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 642d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 652d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_ff_effect_from_user(const char __user *buffer, size_t size, 662d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct ff_effect *effect) 672d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 682d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (INPUT_COMPAT_TEST) { 692d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct ff_effect_compat *compat_effect; 702d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 712d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (size != sizeof(struct ff_effect_compat)) 722d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EINVAL; 732d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 742d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale /* 752d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * It so happens that the pointer which needs to be changed 762d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * is the last field in the structure, so we can retrieve the 772d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * whole thing and replace just the pointer. 782d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale */ 792d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_effect = (struct ff_effect_compat *)effect; 802d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 812d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(compat_effect, buffer, 822d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale sizeof(struct ff_effect_compat))) 832d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 842d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 852d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (compat_effect->type == FF_PERIODIC && 862d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_effect->u.periodic.waveform == FF_CUSTOM) 872d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale effect->u.periodic.custom_data = 882d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale compat_ptr(compat_effect->u.periodic.custom_data); 892d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } else { 902d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (size != sizeof(struct ff_effect)) 912d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EINVAL; 922d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 932d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 942d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 952d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale } 962d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 972d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 982d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 992d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1002d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#else 1012d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1022d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_from_user(const char __user *buffer, 1032d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct input_event *event) 1042d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 1052d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(event, buffer, sizeof(struct input_event))) 1062d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 1072d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1082d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 1092d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 1102d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1112d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_to_user(char __user *buffer, 1122d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale const struct input_event *event) 1132d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 1142d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_to_user(buffer, event, sizeof(struct input_event))) 1152d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 1162d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1172d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 1182d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 1192d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1202d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_ff_effect_from_user(const char __user *buffer, size_t size, 1212d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale struct ff_effect *effect) 1222d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{ 1232d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (size != sizeof(struct ff_effect)) 1242d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EINVAL; 1252d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1262d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 1272d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return -EFAULT; 1282d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1292d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale return 0; 1302d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale} 1312d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1322d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#endif /* CONFIG_COMPAT */ 1332d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale 1342d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_event_from_user); 1352d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_event_to_user); 1362d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_ff_effect_from_user); 137