Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux
[firefly-linux-kernel-4.4.55.git] / drivers / input / input-compat.c
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 <asm/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 (INPUT_COMPAT_TEST && !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 (INPUT_COMPAT_TEST && !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 (INPUT_COMPAT_TEST) {
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);