File Index
Files and directories
Sign in
FILE

input-compat.c

File preview with syntax highlighting.

linux-6.19.14/drivers/input/input-compat.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * 32bit compatibility wrappers for the input subsystem.
  4 *
  5 * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
  6 */
  7
  8#include <linux/export.h>
  9#include <linux/sprintf.h>
 10#include <linux/uaccess.h>
 11#include "input-compat.h"
 12
 13#ifdef CONFIG_COMPAT
 14
 15int input_event_from_user(const char __user *buffer,
 16			  struct input_event *event)
 17{
 18	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
 19		struct input_event_compat compat_event;
 20
 21		if (copy_from_user(&compat_event, buffer,
 22				   sizeof(struct input_event_compat)))
 23			return -EFAULT;
 24
 25		event->input_event_sec = compat_event.sec;
 26		event->input_event_usec = compat_event.usec;
 27		event->type = compat_event.type;
 28		event->code = compat_event.code;
 29		event->value = compat_event.value;
 30
 31	} else {
 32		if (copy_from_user(event, buffer, sizeof(struct input_event)))
 33			return -EFAULT;
 34	}
 35
 36	return 0;
 37}
 38
 39int input_event_to_user(char __user *buffer,
 40			const struct input_event *event)
 41{
 42	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
 43		struct input_event_compat compat_event;
 44
 45		compat_event.sec = event->input_event_sec;
 46		compat_event.usec = event->input_event_usec;
 47		compat_event.type = event->type;
 48		compat_event.code = event->code;
 49		compat_event.value = event->value;
 50
 51		if (copy_to_user(buffer, &compat_event,
 52				 sizeof(struct input_event_compat)))
 53			return -EFAULT;
 54
 55	} else {
 56		if (copy_to_user(buffer, event, sizeof(struct input_event)))
 57			return -EFAULT;
 58	}
 59
 60	return 0;
 61}
 62
 63int input_ff_effect_from_user(const char __user *buffer, size_t size,
 64			      struct ff_effect *effect)
 65{
 66	if (in_compat_syscall()) {
 67		struct ff_effect_compat *compat_effect;
 68
 69		if (size != sizeof(struct ff_effect_compat))
 70			return -EINVAL;
 71
 72		/*
 73		 * It so happens that the pointer which needs to be changed
 74		 * is the last field in the structure, so we can retrieve the
 75		 * whole thing and replace just the pointer.
 76		 */
 77		compat_effect = (struct ff_effect_compat *)effect;
 78
 79		if (copy_from_user(compat_effect, buffer,
 80				   sizeof(struct ff_effect_compat)))
 81			return -EFAULT;
 82
 83		if (compat_effect->type == FF_PERIODIC &&
 84		    compat_effect->u.periodic.waveform == FF_CUSTOM)
 85			effect->u.periodic.custom_data =
 86				compat_ptr(compat_effect->u.periodic.custom_data);
 87	} else {
 88		if (size != sizeof(struct ff_effect))
 89			return -EINVAL;
 90
 91		if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
 92			return -EFAULT;
 93	}
 94
 95	return 0;
 96}
 97
 98int input_bits_to_string(char *buf, int buf_size, unsigned long bits,
 99			 bool skip_empty)
100{
101	int len = 0;
102
103	if (in_compat_syscall()) {
104		u32 dword = bits >> 32;
105		if (dword || !skip_empty)
106			len += snprintf(buf, buf_size, "%x ", dword);
107
108		dword = bits & 0xffffffffUL;
109		if (dword || !skip_empty || len)
110			len += snprintf(buf + len, max(buf_size - len, 0),
111					"%x", dword);
112	} else {
113		if (bits || !skip_empty)
114			len += snprintf(buf, buf_size, "%lx", bits);
115	}
116
117	return len;
118}
119
120#else
121
122int input_event_from_user(const char __user *buffer,
123			 struct input_event *event)
124{
125	if (copy_from_user(event, buffer, sizeof(struct input_event)))
126		return -EFAULT;
127
128	return 0;
129}
130
131int input_event_to_user(char __user *buffer,
132			const struct input_event *event)
133{
134	if (copy_to_user(buffer, event, sizeof(struct input_event)))
135		return -EFAULT;
136
137	return 0;
138}
139
140int input_ff_effect_from_user(const char __user *buffer, size_t size,
141			      struct ff_effect *effect)
142{
143	if (size != sizeof(struct ff_effect))
144		return -EINVAL;
145
146	if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
147		return -EFAULT;
148
149	return 0;
150}
151
152int input_bits_to_string(char *buf, int buf_size, unsigned long bits,
153			 bool skip_empty)
154{
155	return bits || !skip_empty ?
156		snprintf(buf, buf_size, "%lx", bits) : 0;
157}
158
159#endif /* CONFIG_COMPAT */
160
161EXPORT_SYMBOL_GPL(input_event_from_user);
162EXPORT_SYMBOL_GPL(input_event_to_user);
163EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
~/ Read-only file preview.