1 /* 2 * 32bit compatibility wrappers for the input subsystem. 3 * 4 * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published by 8 * the Free Software Foundation. 9 */ 10 11 #include <asm/uaccess.h> 12 #include "input-compat.h" 13 14 #ifdef CONFIG_COMPAT 15 16 int input_event_from_user(const char __user *buffer, 17 struct input_event *event) 18 { 19 if (INPUT_COMPAT_TEST) { 20 struct input_event_compat compat_event; 21 22 if (copy_from_user(&compat_event, buffer, 23 sizeof(struct input_event_compat))) 24 return -EFAULT; 25 26 event->time.tv_sec = compat_event.time.tv_sec; 27 event->time.tv_usec = compat_event.time.tv_usec; 28 event->type = compat_event.type; 29 event->code = compat_event.code; 30 event->value = compat_event.value; 31 32 } else { 33 if (copy_from_user(event, buffer, sizeof(struct input_event))) 34 return -EFAULT; 35 } 36 37 return 0; 38 } 39 40 int input_event_to_user(char __user *buffer, 41 const struct input_event *event) 42 { 43 if (INPUT_COMPAT_TEST) { 44 struct input_event_compat compat_event; 45 46 compat_event.time.tv_sec = event->time.tv_sec; 47 compat_event.time.tv_usec = event->time.tv_usec; 48 compat_event.type = event->type; 49 compat_event.code = event->code; 50 compat_event.value = event->value; 51 52 if (copy_to_user(buffer, &compat_event, 53 sizeof(struct input_event_compat))) 54 return -EFAULT; 55 56 } else { 57 if (copy_to_user(buffer, event, sizeof(struct input_event))) 58 return -EFAULT; 59 } 60 61 return 0; 62 } 63 64 int input_ff_effect_from_user(const char __user *buffer, size_t size, 65 struct ff_effect *effect) 66 { 67 if (INPUT_COMPAT_TEST) { 68 struct ff_effect_compat *compat_effect; 69 70 if (size != sizeof(struct ff_effect_compat)) 71 return -EINVAL; 72 73 /* 74 * It so happens that the pointer which needs to be changed 75 * is the last field in the structure, so we can retrieve the 76 * whole thing and replace just the pointer. 77 */ 78 compat_effect = (struct ff_effect_compat *)effect; 79 80 if (copy_from_user(compat_effect, buffer, 81 sizeof(struct ff_effect_compat))) 82 return -EFAULT; 83 84 if (compat_effect->type == FF_PERIODIC && 85 compat_effect->u.periodic.waveform == FF_CUSTOM) 86 effect->u.periodic.custom_data = 87 compat_ptr(compat_effect->u.periodic.custom_data); 88 } else { 89 if (size != sizeof(struct ff_effect)) 90 return -EINVAL; 91 92 if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 93 return -EFAULT; 94 } 95 96 return 0; 97 } 98 99 #else 100 101 int input_event_from_user(const char __user *buffer, 102 struct input_event *event) 103 { 104 if (copy_from_user(event, buffer, sizeof(struct input_event))) 105 return -EFAULT; 106 107 return 0; 108 } 109 110 int input_event_to_user(char __user *buffer, 111 const struct input_event *event) 112 { 113 if (copy_to_user(buffer, event, sizeof(struct input_event))) 114 return -EFAULT; 115 116 return 0; 117 } 118 119 int input_ff_effect_from_user(const char __user *buffer, size_t size, 120 struct ff_effect *effect) 121 { 122 if (size != sizeof(struct ff_effect)) 123 return -EINVAL; 124 125 if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 126 return -EFAULT; 127 128 return 0; 129 } 130 131 #endif /* CONFIG_COMPAT */ 132 133 EXPORT_SYMBOL_GPL(input_event_from_user); 134 EXPORT_SYMBOL_GPL(input_event_to_user); 135 EXPORT_SYMBOL_GPL(input_ff_effect_from_user); 136