forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.1 KiB
133 lines
3.1 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* 32bit compatibility wrappers for the input subsystem. |
|
* |
|
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik |
|
*/ |
|
|
|
#include <linux/export.h> |
|
#include <linux/uaccess.h> |
|
#include "input-compat.h" |
|
|
|
#ifdef CONFIG_COMPAT |
|
|
|
int input_event_from_user(const char __user *buffer, |
|
struct input_event *event) |
|
{ |
|
if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) { |
|
struct input_event_compat compat_event; |
|
|
|
if (copy_from_user(&compat_event, buffer, |
|
sizeof(struct input_event_compat))) |
|
return -EFAULT; |
|
|
|
event->input_event_sec = compat_event.sec; |
|
event->input_event_usec = compat_event.usec; |
|
event->type = compat_event.type; |
|
event->code = compat_event.code; |
|
event->value = compat_event.value; |
|
|
|
} else { |
|
if (copy_from_user(event, buffer, sizeof(struct input_event))) |
|
return -EFAULT; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int input_event_to_user(char __user *buffer, |
|
const struct input_event *event) |
|
{ |
|
if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) { |
|
struct input_event_compat compat_event; |
|
|
|
compat_event.sec = event->input_event_sec; |
|
compat_event.usec = event->input_event_usec; |
|
compat_event.type = event->type; |
|
compat_event.code = event->code; |
|
compat_event.value = event->value; |
|
|
|
if (copy_to_user(buffer, &compat_event, |
|
sizeof(struct input_event_compat))) |
|
return -EFAULT; |
|
|
|
} else { |
|
if (copy_to_user(buffer, event, sizeof(struct input_event))) |
|
return -EFAULT; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int input_ff_effect_from_user(const char __user *buffer, size_t size, |
|
struct ff_effect *effect) |
|
{ |
|
if (in_compat_syscall()) { |
|
struct ff_effect_compat *compat_effect; |
|
|
|
if (size != sizeof(struct ff_effect_compat)) |
|
return -EINVAL; |
|
|
|
/* |
|
* It so happens that the pointer which needs to be changed |
|
* is the last field in the structure, so we can retrieve the |
|
* whole thing and replace just the pointer. |
|
*/ |
|
compat_effect = (struct ff_effect_compat *)effect; |
|
|
|
if (copy_from_user(compat_effect, buffer, |
|
sizeof(struct ff_effect_compat))) |
|
return -EFAULT; |
|
|
|
if (compat_effect->type == FF_PERIODIC && |
|
compat_effect->u.periodic.waveform == FF_CUSTOM) |
|
effect->u.periodic.custom_data = |
|
compat_ptr(compat_effect->u.periodic.custom_data); |
|
} else { |
|
if (size != sizeof(struct ff_effect)) |
|
return -EINVAL; |
|
|
|
if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) |
|
return -EFAULT; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
#else |
|
|
|
int input_event_from_user(const char __user *buffer, |
|
struct input_event *event) |
|
{ |
|
if (copy_from_user(event, buffer, sizeof(struct input_event))) |
|
return -EFAULT; |
|
|
|
return 0; |
|
} |
|
|
|
int input_event_to_user(char __user *buffer, |
|
const struct input_event *event) |
|
{ |
|
if (copy_to_user(buffer, event, sizeof(struct input_event))) |
|
return -EFAULT; |
|
|
|
return 0; |
|
} |
|
|
|
int input_ff_effect_from_user(const char __user *buffer, size_t size, |
|
struct ff_effect *effect) |
|
{ |
|
if (size != sizeof(struct ff_effect)) |
|
return -EINVAL; |
|
|
|
if (copy_from_user(effect, buffer, sizeof(struct ff_effect))) |
|
return -EFAULT; |
|
|
|
return 0; |
|
} |
|
|
|
#endif /* CONFIG_COMPAT */ |
|
|
|
EXPORT_SYMBOL_GPL(input_event_from_user); |
|
EXPORT_SYMBOL_GPL(input_event_to_user); |
|
EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
|
|
|