Blame view

drivers/input/input-compat.c 3.14 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
2d56f3a32   Philip Langdale   Input: refactor e...
2
3
4
5
  /*
   * 32bit compatibility wrappers for the input subsystem.
   *
   * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
2d56f3a32   Philip Langdale   Input: refactor e...
6
   */
15d0580f2   Paul Gortmaker   drivers/input: ad...
7
  #include <linux/export.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
8
  #include <linux/uaccess.h>
2d56f3a32   Philip Langdale   Input: refactor e...
9
10
11
12
13
14
15
  #include "input-compat.h"
  
  #ifdef CONFIG_COMPAT
  
  int input_event_from_user(const char __user *buffer,
  			  struct input_event *event)
  {
b8b4ead11   Andrew Morton   drivers/input: el...
16
  	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
2d56f3a32   Philip Langdale   Input: refactor e...
17
18
19
20
21
  		struct input_event_compat compat_event;
  
  		if (copy_from_user(&compat_event, buffer,
  				   sizeof(struct input_event_compat)))
  			return -EFAULT;
152194fe9   Deepa Dinamani   Input: extend usa...
22
23
  		event->input_event_sec = compat_event.sec;
  		event->input_event_usec = compat_event.usec;
2d56f3a32   Philip Langdale   Input: refactor e...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
  		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)
  {
b8b4ead11   Andrew Morton   drivers/input: el...
39
  	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
2d56f3a32   Philip Langdale   Input: refactor e...
40
  		struct input_event_compat compat_event;
152194fe9   Deepa Dinamani   Input: extend usa...
41
42
  		compat_event.sec = event->input_event_sec;
  		compat_event.usec = event->input_event_usec;
2d56f3a32   Philip Langdale   Input: refactor e...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
  		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)
  {
b8b4ead11   Andrew Morton   drivers/input: el...
62
  	if (in_compat_syscall()) {
2d56f3a32   Philip Langdale   Input: refactor e...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
  		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);