--- 2.6.24-gentoo-r3/drivers/input/evdev.c 2008-01-24 23:58:37.000000000 +0100 +++ 2.6.24-gentoo-r3/drivers/input/evdev.c 2008-03-25 15:16:26.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,27 @@ 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) + 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))) --- 2.6.24-gentoo-r3/include/linux/input.h 2008-01-24 23:58:37.000000000 +0100 +++ 2.6.24-gentoo-r3/include/linux/input.h 2008-03-24 11:47:51.000000000 +0100 @@ -12,6 +12,7 @@ #ifdef __KERNEL__ #include #include +#include #else #include #include @@ -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) /* send a force effect to a force feedback device */ +#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 */ @@ -1362,6 +1399,9 @@ void input_ff_destroy(struct input_dev * int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code, int value); int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file); +#ifdef CONFIG_COMPAT +int input_ff_upload32(struct input_dev *dev, struct ff_effect32 *effect32, struct file *file); +#endif int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file); int input_ff_create_memless(struct input_dev *dev, void *data,