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