All of lore.kernel.org
 help / color / mirror / Atom feed
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.