134 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * 32bit compatibility wrappers for the input subsystem.4 *5 * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik6 */7 8#include <linux/export.h>9#include <linux/uaccess.h>10#include "input-compat.h"11 12#ifdef CONFIG_COMPAT13 14int input_event_from_user(const char __user *buffer,15 struct input_event *event)16{17 if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {18 struct input_event_compat compat_event;19 20 if (copy_from_user(&compat_event, buffer,21 sizeof(struct input_event_compat)))22 return -EFAULT;23 24 event->input_event_sec = compat_event.sec;25 event->input_event_usec = compat_event.usec;26 event->type = compat_event.type;27 event->code = compat_event.code;28 event->value = compat_event.value;29 30 } else {31 if (copy_from_user(event, buffer, sizeof(struct input_event)))32 return -EFAULT;33 }34 35 return 0;36}37 38int input_event_to_user(char __user *buffer,39 const struct input_event *event)40{41 if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {42 struct input_event_compat compat_event;43 44 compat_event.sec = event->input_event_sec;45 compat_event.usec = event->input_event_usec;46 compat_event.type = event->type;47 compat_event.code = event->code;48 compat_event.value = event->value;49 50 if (copy_to_user(buffer, &compat_event,51 sizeof(struct input_event_compat)))52 return -EFAULT;53 54 } else {55 if (copy_to_user(buffer, event, sizeof(struct input_event)))56 return -EFAULT;57 }58 59 return 0;60}61 62int input_ff_effect_from_user(const char __user *buffer, size_t size,63 struct ff_effect *effect)64{65 if (in_compat_syscall()) {66 struct ff_effect_compat *compat_effect;67 68 if (size != sizeof(struct ff_effect_compat))69 return -EINVAL;70 71 /*72 * It so happens that the pointer which needs to be changed73 * is the last field in the structure, so we can retrieve the74 * whole thing and replace just the pointer.75 */76 compat_effect = (struct ff_effect_compat *)effect;77 78 if (copy_from_user(compat_effect, buffer,79 sizeof(struct ff_effect_compat)))80 return -EFAULT;81 82 if (compat_effect->type == FF_PERIODIC &&83 compat_effect->u.periodic.waveform == FF_CUSTOM)84 effect->u.periodic.custom_data =85 compat_ptr(compat_effect->u.periodic.custom_data);86 } else {87 if (size != sizeof(struct ff_effect))88 return -EINVAL;89 90 if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))91 return -EFAULT;92 }93 94 return 0;95}96 97#else98 99int input_event_from_user(const char __user *buffer,100 struct input_event *event)101{102 if (copy_from_user(event, buffer, sizeof(struct input_event)))103 return -EFAULT;104 105 return 0;106}107 108int input_event_to_user(char __user *buffer,109 const struct input_event *event)110{111 if (copy_to_user(buffer, event, sizeof(struct input_event)))112 return -EFAULT;113 114 return 0;115}116 117int input_ff_effect_from_user(const char __user *buffer, size_t size,118 struct ff_effect *effect)119{120 if (size != sizeof(struct ff_effect))121 return -EINVAL;122 123 if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))124 return -EFAULT;125 126 return 0;127}128 129#endif /* CONFIG_COMPAT */130 131EXPORT_SYMBOL_GPL(input_event_from_user);132EXPORT_SYMBOL_GPL(input_event_to_user);133EXPORT_SYMBOL_GPL(input_ff_effect_from_user);134