From: drAke <drake@oomkill.net>
To: linux-input@vger.kernel.org
Cc: Adam Dawidowski <drake@oomkill.net>
Subject: [PATCH] Fix force feedback uploading for 32-bit apps on 64-bit kernel
Date: Thu, 27 Mar 2008 22:20:18 +0100 [thread overview]
Message-ID: <47EC0F92.7070106@oomkill.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 646 bytes --]
Hello,
Force feedback upload of effects through the event device (ioctl
EVIOCSFF) is not working in 32 bit apps like wine on a 64-bit kernel. 64
bit apps like fftest work.
This is due to the fact that struct ff_effect contains a pointer,
resulting in the structure having different sizes in 64 and 32 bit
programs. This means that the ioctl issued from 32 bit code isn't
handled, because it has a different number.
Attached patch (against 2.6.24.3) fixes this. Tested on x86_64.
Is this ok or are there some alignment issues, which forbid this simple
zero-copy solution?
PS. Please keep me in the CC list, as I'm not subscribing this list.
[-- Attachment #2: ioctl_EVIOCSFF_32bit_fix.patch --]
[-- Type: text/plain, Size: 3492 bytes --]
diff -ruNp 2.6.24.3/drivers/input/evdev.c 2.6.24.3-ioctl-fix/drivers/input/evdev.c
--- 2.6.24.3/drivers/input/evdev.c 2008-01-24 23:58:37.000000000 +0100
+++ 2.6.24.3-ioctl-fix/drivers/input/evdev.c 2008-03-26 22:12:02.000000000 +0100
@@ -577,6 +577,9 @@ static long evdev_do_ioctl(struct file *
struct input_dev *dev = evdev->handle.dev;
struct input_absinfo abs;
struct ff_effect effect;
+#ifdef CONFIG_COMPAT
+ struct ff_effect32 *effect32;
+#endif
int __user *ip = (int __user *)p;
int i, t, u, v;
int error;
@@ -632,10 +635,28 @@ static long evdev_do_ioctl(struct file *
return dev->setkeycode(dev, t, v);
+#ifdef CONFIG_COMPAT
+ case EVIOCSFF32:
+#endif
case EVIOCSFF:
- if (copy_from_user(&effect, p, sizeof(effect)))
+ if (copy_from_user(&effect, p, _IOC_SIZE(cmd)))
return -EFAULT;
+#ifdef CONFIG_COMPAT
+ /*
+ * It so happens that the pointer which needs to be changed
+ * is the last field in the structure, so we can copy the
+ * whole thing and replace just the pointer.
+ */
+ if (cmd == EVIOCSFF32) {
+ effect32 = (struct ff_effect32 *)&effect;
+ if (effect32->type == FF_PERIODIC &&
+ effect32->u.periodic.waveform == FF_CUSTOM)
+ effect.u.periodic.custom_data = compat_ptr(
+ effect32->u.periodic.custom_data);
+ }
+#endif
+
error = input_ff_upload(dev, &effect, file);
if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
diff -ruNp 2.6.24.3/include/linux/input.h 2.6.24.3-ioctl-fix/include/linux/input.h
--- 2.6.24.3/include/linux/input.h 2008-01-24 23:58:37.000000000 +0100
+++ 2.6.24.3-ioctl-fix/include/linux/input.h 2008-03-25 22:17:59.000000000 +0100
@@ -12,6 +12,7 @@
#ifdef __KERNEL__
#include <linux/time.h>
#include <linux/list.h>
+#include <linux/compat.h>
#else
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -75,7 +76,10 @@ struct input_absinfo {
#define EVIOCGABS(abs) _IOR('E', 0x40 + abs, struct input_absinfo) /* get abs value/limits */
#define EVIOCSABS(abs) _IOW('E', 0xc0 + abs, struct input_absinfo) /* set abs value/limits */
-#define EVIOCSFF _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect)) /* send a force effect to a force feedback device */
+#define EVIOCSFF _IOW('E', 0x80, struct ff_effect) /* send a force effect to a force feedback device */
+#ifdef CONFIG_COMPAT
+#define EVIOCSFF32 _IOW('E', 0x80, struct ff_effect32)
+#endif
#define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */
#define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */
@@ -846,6 +850,21 @@ struct ff_periodic_effect {
__s16 *custom_data;
};
+#ifdef CONFIG_COMPAT
+struct ff_periodic_effect32 {
+ __u16 waveform;
+ __u16 period;
+ __s16 magnitude;
+ __s16 offset;
+ __u16 phase;
+
+ struct ff_envelope envelope;
+
+ __u32 custom_len;
+ compat_uptr_t custom_data;
+};
+#endif
+
/**
* struct ff_rumble_effect - defines parameters of a periodic force-feedback effect
* @strong_magnitude: magnitude of the heavy motor
@@ -898,6 +917,24 @@ struct ff_effect {
} u;
};
+#ifdef CONFIG_COMPAT
+struct ff_effect32 {
+ __u16 type;
+ __s16 id;
+ __u16 direction;
+ struct ff_trigger trigger;
+ struct ff_replay replay;
+
+ union {
+ struct ff_constant_effect constant;
+ struct ff_ramp_effect ramp;
+ struct ff_periodic_effect32 periodic;
+ struct ff_condition_effect condition[2]; /* One for each axis */
+ struct ff_rumble_effect rumble;
+ } u;
+};
+#endif
+
/*
* Force feedback effect types
*/
reply other threads:[~2008-03-27 21:29 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=47EC0F92.7070106@oomkill.net \
--to=drake@oomkill.net \
--cc=linux-input@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.