12d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale/*
22d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * 32bit compatibility wrappers for the input subsystem.
32d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale *
42d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik
52d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale *
62d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * This program is free software; you can redistribute it and/or modify it
72d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * under the terms of the GNU General Public License version 2 as published by
82d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale * the Free Software Foundation.
92d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale */
102d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1115d0580f20f5d3f997e3823bfe39daa3d521a99dPaul Gortmaker#include <linux/export.h>
122d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#include <asm/uaccess.h>
132d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#include "input-compat.h"
142d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
152d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#ifdef CONFIG_COMPAT
162d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
172d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_from_user(const char __user *buffer,
182d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			  struct input_event *event)
192d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
20f930a7a0f4c87bf3ee731383421ebf3164009ee7H. J. Lu	if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
212d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		struct input_event_compat compat_event;
222d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
232d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_from_user(&compat_event, buffer,
242d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale				   sizeof(struct input_event_compat)))
252d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
262d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
272d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		event->time.tv_sec = compat_event.time.tv_sec;
282d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		event->time.tv_usec = compat_event.time.tv_usec;
292d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		event->type = compat_event.type;
302d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		event->code = compat_event.code;
312d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		event->value = compat_event.value;
322d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
332d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	} else {
342d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_from_user(event, buffer, sizeof(struct input_event)))
352d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
362d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	}
372d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
382d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
392d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
402d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
412d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_to_user(char __user *buffer,
422d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			const struct input_event *event)
432d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
44f930a7a0f4c87bf3ee731383421ebf3164009ee7H. J. Lu	if (INPUT_COMPAT_TEST && !COMPAT_USE_64BIT_TIME) {
452d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		struct input_event_compat compat_event;
462d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
472d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_event.time.tv_sec = event->time.tv_sec;
482d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_event.time.tv_usec = event->time.tv_usec;
492d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_event.type = event->type;
502d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_event.code = event->code;
512d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_event.value = event->value;
522d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
532d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_to_user(buffer, &compat_event,
542d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale				 sizeof(struct input_event_compat)))
552d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
562d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
572d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	} else {
582d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_to_user(buffer, event, sizeof(struct input_event)))
592d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
602d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	}
612d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
622d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
632d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
642d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
652d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_ff_effect_from_user(const char __user *buffer, size_t size,
662d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			      struct ff_effect *effect)
672d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
682d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	if (INPUT_COMPAT_TEST) {
692d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		struct ff_effect_compat *compat_effect;
702d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
712d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (size != sizeof(struct ff_effect_compat))
722d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EINVAL;
732d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
742d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		/*
752d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		 * It so happens that the pointer which needs to be changed
762d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		 * is the last field in the structure, so we can retrieve the
772d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		 * whole thing and replace just the pointer.
782d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		 */
792d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		compat_effect = (struct ff_effect_compat *)effect;
802d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
812d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_from_user(compat_effect, buffer,
822d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale				   sizeof(struct ff_effect_compat)))
832d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
842d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
852d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (compat_effect->type == FF_PERIODIC &&
862d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		    compat_effect->u.periodic.waveform == FF_CUSTOM)
872d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			effect->u.periodic.custom_data =
882d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale				compat_ptr(compat_effect->u.periodic.custom_data);
892d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	} else {
902d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (size != sizeof(struct ff_effect))
912d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EINVAL;
922d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
932d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
942d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			return -EFAULT;
952d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	}
962d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
972d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
982d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
992d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1002d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#else
1012d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1022d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_from_user(const char __user *buffer,
1032d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			 struct input_event *event)
1042d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
1052d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	if (copy_from_user(event, buffer, sizeof(struct input_event)))
1062d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		return -EFAULT;
1072d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1082d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
1092d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
1102d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1112d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_event_to_user(char __user *buffer,
1122d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			const struct input_event *event)
1132d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
1142d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	if (copy_to_user(buffer, event, sizeof(struct input_event)))
1152d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		return -EFAULT;
1162d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1172d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
1182d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
1192d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1202d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdaleint input_ff_effect_from_user(const char __user *buffer, size_t size,
1212d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale			      struct ff_effect *effect)
1222d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale{
1232d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	if (size != sizeof(struct ff_effect))
1242d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		return -EINVAL;
1252d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1262d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	if (copy_from_user(effect, buffer, sizeof(struct ff_effect)))
1272d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale		return -EFAULT;
1282d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1292d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale	return 0;
1302d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale}
1312d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1322d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale#endif /* CONFIG_COMPAT */
1332d56f3a32c0e62f99c043d2579840f9731fe5855Philip Langdale
1342d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_event_from_user);
1352d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_event_to_user);
1362d56f3a32c0e62f99c043d2579840f9731fe5855Philip LangdaleEXPORT_SYMBOL_GPL(input_ff_effect_from_user);
137