Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * 32bit compatibility wrappers for the input subsystem.
0004  *
0005  * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
0006  */
0007 
0008 #include <linux/export.h>
0009 #include <linux/uaccess.h>
0010 #include "input-compat.h"
0011 
0012 #ifdef CONFIG_COMPAT
0013 
0014 int input_event_from_user(const char __user *buffer,
0015               struct input_event *event)
0016 {
0017     if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
0018         struct input_event_compat compat_event;
0019 
0020         if (copy_from_user(&compat_event, buffer,
0021                    sizeof(struct input_event_compat)))
0022             return -EFAULT;
0023 
0024         event->input_event_sec = compat_event.sec;
0025         event->input_event_usec = compat_event.usec;
0026         event->type = compat_event.type;
0027         event->code = compat_event.code;
0028         event->value = compat_event.value;
0029 
0030     } else {
0031         if (copy_from_user(event, buffer, sizeof(struct input_event)))
0032             return -EFAULT;
0033     }
0034 
0035     return 0;
0036 }
0037 
0038 int input_event_to_user(char __user *buffer,
0039             const struct input_event *event)
0040 {
0041     if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
0042         struct input_event_compat compat_event;
0043 
0044         compat_event.sec = event->input_event_sec;
0045         compat_event.usec = event->input_event_usec;
0046         compat_event.type = event->type;
0047         compat_event.code = event->code;
0048         compat_event.value = event->value;
0049 
0050         if (copy_to_user(buffer, &compat_event,
0051                  sizeof(struct input_event_compat)))
0052             return -EFAULT;
0053 
0054     } else {
0055         if (copy_to_user(buffer, event, sizeof(struct input_event)))
0056             return -EFAULT;
0057     }
0058 
0059     return 0;
0060 }
0061 
0062 int input_ff_effect_from_user(const char __user *buffer, size_t size,
0063                   struct ff_effect *effect)
0064 {
0065     if (in_compat_syscall()) {
0066         struct ff_effect_compat *compat_effect;
0067 
0068         if (size != sizeof(struct ff_effect_compat))
0069             return -EINVAL;
0070 
0071         /*
0072          * It so happens that the pointer which needs to be changed
0073          * is the last field in the structure, so we can retrieve the
0074          * whole thing and replace just the pointer.
0075          */
0076         compat_effect = (struct ff_effect_compat *)effect;
0077 
0078         if (copy_from_user(compat_effect, buffer,
0079                    sizeof(struct ff_effect_compat)))
0080             return -EFAULT;
0081 
0082         if (compat_effect->type == FF_PERIODIC &&
0083             compat_effect->u.periodic.waveform == FF_CUSTOM)
0084             effect->u.periodic.custom_data =
0085                 compat_ptr(compat_effect->u.periodic.custom_data);
0086     } else {
0087         if (size != sizeof(struct ff_effect))
0088             return -EINVAL;
0089 
0090         if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
0091             return -EFAULT;
0092     }
0093 
0094     return 0;
0095 }
0096 
0097 #else
0098 
0099 int input_event_from_user(const char __user *buffer,
0100              struct input_event *event)
0101 {
0102     if (copy_from_user(event, buffer, sizeof(struct input_event)))
0103         return -EFAULT;
0104 
0105     return 0;
0106 }
0107 
0108 int input_event_to_user(char __user *buffer,
0109             const struct input_event *event)
0110 {
0111     if (copy_to_user(buffer, event, sizeof(struct input_event)))
0112         return -EFAULT;
0113 
0114     return 0;
0115 }
0116 
0117 int input_ff_effect_from_user(const char __user *buffer, size_t size,
0118                   struct ff_effect *effect)
0119 {
0120     if (size != sizeof(struct ff_effect))
0121         return -EINVAL;
0122 
0123     if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
0124         return -EFAULT;
0125 
0126     return 0;
0127 }
0128 
0129 #endif /* CONFIG_COMPAT */
0130 
0131 EXPORT_SYMBOL_GPL(input_event_from_user);
0132 EXPORT_SYMBOL_GPL(input_event_to_user);
0133 EXPORT_SYMBOL_GPL(input_ff_effect_from_user);