-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Input: refactor evdev 32bit compat to be shareable with uinput
Currently, evdev has working 32bit compatibility and uinput does not. uinput needs the input_event code that evdev uses, so let's refactor it so it can be shared. [dtor@mail.ru: add fix for force feedback compat issues] Signed-off-by: Philip Langdale <philipl@overt.org> Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
- Loading branch information
Philip Langdale
authored and
Dmitry Torokhov
committed
Oct 28, 2008
1 parent
49fdf67
commit 2d56f3a
Showing
5 changed files
with
383 additions
and
217 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/* | ||
* 32bit compatibility wrappers for the input subsystem. | ||
* | ||
* Very heavily based on evdev.c - Copyright (c) 1999-2002 Vojtech Pavlik | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 as published by | ||
* the Free Software Foundation. | ||
*/ | ||
|
||
#include <asm/uaccess.h> | ||
#include "input-compat.h" | ||
|
||
#ifdef CONFIG_COMPAT | ||
|
||
int input_event_from_user(const char __user *buffer, | ||
struct input_event *event) | ||
{ | ||
if (INPUT_COMPAT_TEST) { | ||
struct input_event_compat compat_event; | ||
|
||
if (copy_from_user(&compat_event, buffer, | ||
sizeof(struct input_event_compat))) | ||
return -EFAULT; | ||
|
||
event->time.tv_sec = compat_event.time.tv_sec; | ||
event->time.tv_usec = compat_event.time.tv_usec; | ||
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) | ||
{ | ||
if (INPUT_COMPAT_TEST) { | ||
struct input_event_compat compat_event; | ||
|
||
compat_event.time.tv_sec = event->time.tv_sec; | ||
compat_event.time.tv_usec = event->time.tv_usec; | ||
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) | ||
{ | ||
if (INPUT_COMPAT_TEST) { | ||
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); |
Oops, something went wrong.