diff options
author | Anssi Hannula <anssi.hannula@gmail.com> | 2006-07-19 01:40:22 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor@insightbb.com> | 2006-07-19 01:40:22 -0400 |
commit | 509ca1a9383601fdc5612d3d3ba5b981f6eb6c8b (patch) | |
tree | 4d7b63c2b108510c11a89dc0ea45efe788fed779 /drivers/input/evdev.c | |
parent | 806d41b756fecc1b13584e2b806b76d8934b1679 (diff) |
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.c | 32 |
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, | |||
391 | struct evdev *evdev = list->evdev; | 391 | struct evdev *evdev = list->evdev; |
392 | struct input_dev *dev = evdev->handle.dev; | 392 | struct input_dev *dev = evdev->handle.dev; |
393 | struct input_absinfo abs; | 393 | struct input_absinfo abs; |
394 | struct ff_effect effect; | ||
394 | int __user *ip = (int __user *)p; | 395 | int __user *ip = (int __user *)p; |
395 | int i, t, u, v; | 396 | int i, t, u, v; |
397 | int error; | ||
396 | 398 | ||
397 | if (!evdev->exist) | 399 | if (!evdev->exist) |
398 | return -ENODEV; | 400 | return -ENODEV; |
@@ -460,27 +462,22 @@ static long evdev_ioctl_handler(struct file *file, unsigned int cmd, | |||
460 | return 0; | 462 | return 0; |
461 | 463 | ||
462 | case EVIOCSFF: | 464 | case EVIOCSFF: |
463 | if (dev->upload_effect) { | 465 | if (copy_from_user(&effect, p, sizeof(effect))) |
464 | struct ff_effect effect; | 466 | return -EFAULT; |
465 | int err; | ||
466 | |||
467 | if (copy_from_user(&effect, p, sizeof(effect))) | ||
468 | return -EFAULT; | ||
469 | err = dev->upload_effect(dev, &effect); | ||
470 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) | ||
471 | return -EFAULT; | ||
472 | return err; | ||
473 | } else | ||
474 | return -ENOSYS; | ||
475 | 467 | ||
476 | case EVIOCRMFF: | 468 | error = input_ff_upload(dev, &effect, file); |
477 | if (!dev->erase_effect) | ||
478 | return -ENOSYS; | ||
479 | 469 | ||
480 | return dev->erase_effect(dev, (int)(unsigned long) p); | 470 | if (put_user(effect.id, &(((struct ff_effect __user *)p)->id))) |
471 | return -EFAULT; | ||
472 | |||
473 | return error; | ||
474 | |||
475 | case EVIOCRMFF: | ||
476 | return input_ff_erase(dev, (int)(unsigned long) p, file); | ||
481 | 477 | ||
482 | case EVIOCGEFFECTS: | 478 | case EVIOCGEFFECTS: |
483 | if (put_user(dev->ff_effects_max, ip)) | 479 | i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; |
480 | if (put_user(i, ip)) | ||
484 | return -EFAULT; | 481 | return -EFAULT; |
485 | return 0; | 482 | return 0; |
486 | 483 | ||
@@ -669,6 +666,7 @@ static void evdev_disconnect(struct input_handle *handle) | |||
669 | evdev->exist = 0; | 666 | evdev->exist = 0; |
670 | 667 | ||
671 | if (evdev->open) { | 668 | if (evdev->open) { |
669 | input_flush_device(handle, NULL); | ||
672 | input_close_device(handle); | 670 | input_close_device(handle); |
673 | wake_up_interruptible(&evdev->wait); | 671 | wake_up_interruptible(&evdev->wait); |
674 | list_for_each_entry(list, &evdev->list, node) | 672 | list_for_each_entry(list, &evdev->list, node) |