xref: /openbmc/linux/drivers/input/input-compat.c (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22d56f3a3SPhilip Langdale /*
32d56f3a3SPhilip Langdale  * 32bit compatibility wrappers for the input subsystem.
42d56f3a3SPhilip Langdale  *
52d56f3a3SPhilip Langdale  * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
62d56f3a3SPhilip Langdale  */
72d56f3a3SPhilip Langdale 
815d0580fSPaul Gortmaker #include <linux/export.h>
97c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
102d56f3a3SPhilip Langdale #include "input-compat.h"
112d56f3a3SPhilip Langdale 
122d56f3a3SPhilip Langdale #ifdef CONFIG_COMPAT
132d56f3a3SPhilip Langdale 
input_event_from_user(const char __user * buffer,struct input_event * event)142d56f3a3SPhilip Langdale int input_event_from_user(const char __user *buffer,
152d56f3a3SPhilip Langdale 			  struct input_event *event)
162d56f3a3SPhilip Langdale {
17b8b4ead1SAndrew Morton 	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
182d56f3a3SPhilip Langdale 		struct input_event_compat compat_event;
192d56f3a3SPhilip Langdale 
202d56f3a3SPhilip Langdale 		if (copy_from_user(&compat_event, buffer,
212d56f3a3SPhilip Langdale 				   sizeof(struct input_event_compat)))
222d56f3a3SPhilip Langdale 			return -EFAULT;
232d56f3a3SPhilip Langdale 
24152194feSDeepa Dinamani 		event->input_event_sec = compat_event.sec;
25152194feSDeepa Dinamani 		event->input_event_usec = compat_event.usec;
262d56f3a3SPhilip Langdale 		event->type = compat_event.type;
272d56f3a3SPhilip Langdale 		event->code = compat_event.code;
282d56f3a3SPhilip Langdale 		event->value = compat_event.value;
292d56f3a3SPhilip Langdale 
302d56f3a3SPhilip Langdale 	} else {
312d56f3a3SPhilip Langdale 		if (copy_from_user(event, buffer, sizeof(struct input_event)))
322d56f3a3SPhilip Langdale 			return -EFAULT;
332d56f3a3SPhilip Langdale 	}
342d56f3a3SPhilip Langdale 
352d56f3a3SPhilip Langdale 	return 0;
362d56f3a3SPhilip Langdale }
372d56f3a3SPhilip Langdale 
input_event_to_user(char __user * buffer,const struct input_event * event)382d56f3a3SPhilip Langdale int input_event_to_user(char __user *buffer,
392d56f3a3SPhilip Langdale 			const struct input_event *event)
402d56f3a3SPhilip Langdale {
41b8b4ead1SAndrew Morton 	if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
422d56f3a3SPhilip Langdale 		struct input_event_compat compat_event;
432d56f3a3SPhilip Langdale 
44152194feSDeepa Dinamani 		compat_event.sec = event->input_event_sec;
45152194feSDeepa Dinamani 		compat_event.usec = event->input_event_usec;
462d56f3a3SPhilip Langdale 		compat_event.type = event->type;
472d56f3a3SPhilip Langdale 		compat_event.code = event->code;
482d56f3a3SPhilip Langdale 		compat_event.value = event->value;
492d56f3a3SPhilip Langdale 
502d56f3a3SPhilip Langdale 		if (copy_to_user(buffer, &compat_event,
512d56f3a3SPhilip Langdale 				 sizeof(struct input_event_compat)))
522d56f3a3SPhilip Langdale 			return -EFAULT;
532d56f3a3SPhilip Langdale 
542d56f3a3SPhilip Langdale 	} else {
552d56f3a3SPhilip Langdale 		if (copy_to_user(buffer, event, sizeof(struct input_event)))
562d56f3a3SPhilip Langdale 			return -EFAULT;
572d56f3a3SPhilip Langdale 	}
582d56f3a3SPhilip Langdale 
592d56f3a3SPhilip Langdale 	return 0;
602d56f3a3SPhilip Langdale }
612d56f3a3SPhilip Langdale 
input_ff_effect_from_user(const char __user * buffer,size_t size,struct ff_effect * effect)622d56f3a3SPhilip Langdale int input_ff_effect_from_user(const char __user *buffer, size_t size,
632d56f3a3SPhilip Langdale 			      struct ff_effect *effect)
642d56f3a3SPhilip Langdale {
65b8b4ead1SAndrew Morton 	if (in_compat_syscall()) {
662d56f3a3SPhilip Langdale 		struct ff_effect_compat *compat_effect;
672d56f3a3SPhilip Langdale 
682d56f3a3SPhilip Langdale 		if (size != sizeof(struct ff_effect_compat))
692d56f3a3SPhilip Langdale 			return -EINVAL;
702d56f3a3SPhilip Langdale 
712d56f3a3SPhilip Langdale 		/*
722d56f3a3SPhilip Langdale 		 * It so happens that the pointer which needs to be changed
732d56f3a3SPhilip Langdale 		 * is the last field in the structure, so we can retrieve the
742d56f3a3SPhilip Langdale 		 * whole thing and replace just the pointer.
752d56f3a3SPhilip Langdale 		 */
762d56f3a3SPhilip Langdale 		compat_effect = (struct ff_effect_compat *)effect;
772d56f3a3SPhilip Langdale 
782d56f3a3SPhilip Langdale 		if (copy_from_user(compat_effect, buffer,
792d56f3a3SPhilip Langdale 				   sizeof(struct ff_effect_compat)))
802d56f3a3SPhilip Langdale 			return -EFAULT;
812d56f3a3SPhilip Langdale 
822d56f3a3SPhilip Langdale 		if (compat_effect->type == FF_PERIODIC &&
832d56f3a3SPhilip Langdale 		    compat_effect->u.periodic.waveform == FF_CUSTOM)
842d56f3a3SPhilip Langdale 			effect->u.periodic.custom_data =
852d56f3a3SPhilip Langdale 				compat_ptr(compat_effect->u.periodic.custom_data);
862d56f3a3SPhilip Langdale 	} else {
872d56f3a3SPhilip Langdale 		if (size != sizeof(struct ff_effect))
882d56f3a3SPhilip Langdale 			return -EINVAL;
892d56f3a3SPhilip Langdale 
902d56f3a3SPhilip Langdale 		if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
912d56f3a3SPhilip Langdale 			return -EFAULT;
922d56f3a3SPhilip Langdale 	}
932d56f3a3SPhilip Langdale 
942d56f3a3SPhilip Langdale 	return 0;
952d56f3a3SPhilip Langdale }
962d56f3a3SPhilip Langdale 
972d56f3a3SPhilip Langdale #else
982d56f3a3SPhilip Langdale 
input_event_from_user(const char __user * buffer,struct input_event * event)992d56f3a3SPhilip Langdale int input_event_from_user(const char __user *buffer,
1002d56f3a3SPhilip Langdale 			 struct input_event *event)
1012d56f3a3SPhilip Langdale {
1022d56f3a3SPhilip Langdale 	if (copy_from_user(event, buffer, sizeof(struct input_event)))
1032d56f3a3SPhilip Langdale 		return -EFAULT;
1042d56f3a3SPhilip Langdale 
1052d56f3a3SPhilip Langdale 	return 0;
1062d56f3a3SPhilip Langdale }
1072d56f3a3SPhilip Langdale 
input_event_to_user(char __user * buffer,const struct input_event * event)1082d56f3a3SPhilip Langdale int input_event_to_user(char __user *buffer,
1092d56f3a3SPhilip Langdale 			const struct input_event *event)
1102d56f3a3SPhilip Langdale {
1112d56f3a3SPhilip Langdale 	if (copy_to_user(buffer, event, sizeof(struct input_event)))
1122d56f3a3SPhilip Langdale 		return -EFAULT;
1132d56f3a3SPhilip Langdale 
1142d56f3a3SPhilip Langdale 	return 0;
1152d56f3a3SPhilip Langdale }
1162d56f3a3SPhilip Langdale 
input_ff_effect_from_user(const char __user * buffer,size_t size,struct ff_effect * effect)1172d56f3a3SPhilip Langdale int input_ff_effect_from_user(const char __user *buffer, size_t size,
1182d56f3a3SPhilip Langdale 			      struct ff_effect *effect)
1192d56f3a3SPhilip Langdale {
1202d56f3a3SPhilip Langdale 	if (size != sizeof(struct ff_effect))
1212d56f3a3SPhilip Langdale 		return -EINVAL;
1222d56f3a3SPhilip Langdale 
1232d56f3a3SPhilip Langdale 	if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
1242d56f3a3SPhilip Langdale 		return -EFAULT;
1252d56f3a3SPhilip Langdale 
1262d56f3a3SPhilip Langdale 	return 0;
1272d56f3a3SPhilip Langdale }
1282d56f3a3SPhilip Langdale 
1292d56f3a3SPhilip Langdale #endif /* CONFIG_COMPAT */
1302d56f3a3SPhilip Langdale 
1312d56f3a3SPhilip Langdale EXPORT_SYMBOL_GPL(input_event_from_user);
1322d56f3a3SPhilip Langdale EXPORT_SYMBOL_GPL(input_event_to_user);
1332d56f3a3SPhilip Langdale EXPORT_SYMBOL_GPL(input_ff_effect_from_user);
134