summary refs log tree commit diff
path: root/drivers/input/evdev.c
diff options
context:
space:
mode:
authorAnssi Hannula <anssi.hannula@gmail.com>2006-07-19 01:40:22 -0400
committerDmitry Torokhov <dtor@insightbb.com>2006-07-19 01:40:22 -0400
commit509ca1a9383601fdc5612d3d3ba5b981f6eb6c8b (patch)
tree4d7b63c2b108510c11a89dc0ea45efe788fed779 /drivers/input/evdev.c
parent806d41b756fecc1b13584e2b806b76d8934b1679 (diff)
downloadlinux-509ca1a9383601fdc5612d3d3ba5b981f6eb6c8b.tar.gz
Input: implement new force feedback interface
Implement a new force feedback interface, in which all non-driver-specific
operations are separated to a common module. This includes handling effect
type validations, locking, etc.

The effects are now file descriptor specific instead of the previous strange
half-process half-fd specific behaviour. The effect memory of devices is not
emptied if the root user opens and closes the device while another user is
using effects. This is a minor change and most likely no force feedback
aware programs are affected by this negatively.

Otherwise the userspace interface is left unaltered.

Signed-off-by: Anssi Hannula <anssi.hannula@gmail.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
Diffstat (limited to 'drivers/input/evdev.c')
-rw-r--r--drivers/input/evdev.c32
1 files changed, 15 insertions, 17 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 4bf48188cc91..12c7ab876c34 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -391,8 +391,10 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 	struct evdev *evdev = list->evdev;
 	struct input_dev *dev = evdev->handle.dev;
 	struct input_absinfo abs;
+	struct ff_effect effect;
 	int __user *ip = (int __user *)p;
 	int i, t, u, v;
+	int error;
 
 	if (!evdev->exist)
 		return -ENODEV;
@@ -460,27 +462,22 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd,
 			return 0;
 
 		case EVIOCSFF:
-			if (dev->upload_effect) {
-				struct ff_effect effect;
-				int err;
-
-				if (copy_from_user(&effect, p, sizeof(effect)))
-					return -EFAULT;
-				err = dev->upload_effect(dev, &effect);
-				if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
-					return -EFAULT;
-				return err;
-			} else
-				return -ENOSYS;
+			if (copy_from_user(&effect, p, sizeof(effect)))
+				return -EFAULT;
 
-		case EVIOCRMFF:
-			if (!dev->erase_effect)
-				return -ENOSYS;
+			error = input_ff_upload(dev, &effect, file);
 
-			return dev->erase_effect(dev, (int)(unsigned long) p);
+			if (put_user(effect.id, &(((struct ff_effect __user *)p)->id)))
+				return -EFAULT;
+
+			return error;
+
+		case EVIOCRMFF:
+			return input_ff_erase(dev, (int)(unsigned long) p, file);
 
 		case EVIOCGEFFECTS:
-			if (put_user(dev->ff_effects_max, ip))
+			i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0;
+			if (put_user(i, ip))
 				return -EFAULT;
 			return 0;
 
@@ -669,6 +666,7 @@ static void evdev_disconnect(struct input_handle *handle)
 	evdev->exist = 0;
 
 	if (evdev->open) {
+		input_flush_device(handle, NULL);
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
 		list_for_each_entry(list, &evdev->list, node)