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 <linux/export.h> 12 #include <linux/uaccess.h> 13 #include "input-compat.h" 14 15 #ifdef CONFIG_COMPAT 16 17 int input_event_from_user(const char __user *buffer, 18 struct input_event *event) 19 { 20 if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) { 21 struct input_event_compat compat_event; 22 23 if (copy_from_user(&compat_event, buffer, 24 sizeof(struct input_event_compat))) 25 return -EFAULT; 26 27 event->time.tv_sec = compat_event.time.tv_sec; 28 event->time.tv_usec = compat_event.time.tv_usec; 29 event->type = compat_event.type; 30 event->code = compat_event.code; 31 event->value = compat_event.value; 32 33 } else { 34 if (copy_from_user(event, buffer, sizeof(struct input_event))) 35 return -EFAULT; 36 } 37 38 return 0; 39 } 40 41 int input_event_to_user(char __user *buffer, 42 const struct input_event *event) 43 { 44 if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) { 45 struct input_event_compat compat_event; 46 47 compat_event.time.tv_sec = event->time.tv_sec; 48 compat_event.time.tv_usec = event->time.tv_usec; 49 compat_event.type = event->type; 50 compat_event.code = event->code; 51 compat_event.value = event->value; 52 53 if (copy_to_user(buffer, &compat_event, 54 sizeof(struct input_event_compat))) 55 return -EFAULT; 56 57 } else { 58 if (copy_to_user(buffer, event, sizeof(struct input_event))) 59 return -EFAULT; 60 } 61 62 return 0; 63 } 64 65 int input_ff_effect_from_user(const char __user *buffer, size_t size, 66 struct ff_effect *effect) 67 { 68 if (in_compat_syscall()) { 69 struct ff_effect_compat *compat_effect; 70 71 if (size != sizeof(struct ff_effect_compat)) 72 return -EINVAL; 73 74 /* 75 * It so happens that the pointer which needs to be changed 76 * is the last field in the structure, so we can retrieve the 77 * whole thing and replace just the pointer. 78 */ 79 compat_effect = (struct ff_effect_compat *)effect; 80 81 if (copy_from_user(compat_effect, buffer, 82 sizeof(struct ff_effect_compat))) 83 return -EFAULT; 84 85 if (compat_effect->type == FF_PERIODIC && 86 compat_effect->u.periodic.waveform == FF_CUSTOM) 87 effect->u.periodic.custom_data = 88 compat_ptr(compat_effect->u.periodic.custom_data); 89 } else { 90 if (size != sizeof(struct ff_effect)) 91 return -EINVAL; 92 93 if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 94 return -EFAULT; 95 } 96 97 return 0; 98 } 99 100 #else 101 102 int input_event_from_user(const char __user *buffer, 103 struct input_event *event) 104 { 105 if (copy_from_user(event, buffer, sizeof(struct input_event))) 106 return -EFAULT; 107 108 return 0; 109 } 110 111 int input_event_to_user(char __user *buffer, 112 const struct input_event *event) 113 { 114 if (copy_to_user(buffer, event, sizeof(struct input_event))) 115 return -EFAULT; 116 117 return 0; 118 } 119 120 int input_ff_effect_from_user(const char __user *buffer, size_t size, 121 struct ff_effect *effect) 122 { 123 if (size != sizeof(struct ff_effect)) 124 return -EINVAL; 125 126 if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) 127 return -EFAULT; 128 129 return 0; 130 } 131 132 #endif /* CONFIG_COMPAT */ 133 134 EXPORT_SYMBOL_GPL(input_event_from_user); 135 EXPORT_SYMBOL_GPL(input_event_to_user); 136 EXPORT_SYMBOL_GPL(input_ff_effect_from_user); 137