diff mbox

uinput: RFC uinput memless support

Message ID dbaeaf57-68d7-1fc7-9f6b-d3c07c1d1147@m-reimer.de (mailing list archive)
State New, archived
Headers show

Commit Message

Manuel Reimer May 8, 2016, 4:31 p.m. UTC
Hello,

in the following, I want to show a proof of concept to get pre-made 
rumble events, created by ff-memless on kernel-side, via uinput to usermode.

- All information is passed in the input_event. Currently I use only one 
event, as the int32 value can hold an ff_rumble_effect struct, but, of 
course, it would also be possible to send one event per value with a 
final event to tell usermode to play the last submitted values.
- Does not block kernel-side code.
- Stable. I tried to kill my uinput driver while a game is still 
running, disconnected the gamepad while playing, ... No problems at all.

This first patch is meant to be a basis for discussion. I just did the 
absolute minimum changes to get something, I can test with. If you like 
to see a uinput driver, actually using this, you may have a look at this:

https://github.com/M-Reimer/pspaddrv/blob/memless/device-handler.c#L68

I tried this with Portal 2 and rumble works exactly the same way as it 
does with an Xbox 360 gamepad.

Doing everything in usermode would, of course, be possible. Probably by 
creating a library which can be used from many different drivers. But 
for this to make sense, at first the existing problems with the uinput 
force feedback API would have to be fixed. It isn't much fun to reboot 
the system several times as crashes of the uinput driver daemon 
currently have impact on the uinput kernel module.

Signed-off-by: Manuel Reimer <mail@m-reimer.de>

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff -uprN a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	2016-05-08 11:40:03.211939178 +0200
+++ b/drivers/input/misc/Kconfig	2016-05-08 14:28:33.505991640 +0200
@@ -492,6 +492,7 @@  config INPUT_TWL6040_VIBRA

  config INPUT_UINPUT
  	tristate "User level driver support"
+	select INPUT_FF_MEMLESS
  	help
  	  Say Y here if you want to support user level drivers for input
  	  subsystem accessible under char device 10:223 - /dev/input/uinput.
diff -uprN a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
--- a/drivers/input/misc/uinput.c	2016-05-08 11:40:03.215272511 +0200
+++ b/drivers/input/misc/uinput.c	2016-05-08 18:05:24.138270997 +0200
@@ -230,6 +230,18 @@  static int uinput_dev_erase_effect(struc
  	return uinput_request_submit(udev, &request);
  }

+static int uinput_play_effect(struct input_dev *dev,
+				void *data, struct ff_effect *effect)
+{
+	int value;
+
+	if (effect->type != FF_RUMBLE)
+		return 0;
+
+	memcpy(&value, &effect->u.rumble, sizeof(struct ff_rumble_effect));
+	return uinput_dev_event(dev, EV_UINPUT_MEMLESS, 0, value);
+}
+
  static void uinput_destroy_device(struct uinput_device *udev)
  {
  	const char *name, *phys;
@@ -253,7 +265,7 @@  static void uinput_destroy_device(struct
  	}
  }

-static int uinput_create_device(struct uinput_device *udev)
+static int uinput_create_device(struct uinput_device *udev, int memless)
  {
  	struct input_dev *dev = udev->dev;
  	int error, nslot;
@@ -279,7 +291,12 @@  static int uinput_create_device(struct u
  		goto fail1;
  	}

-	if (udev->ff_effects_max) {
+	if (memless) {
+		input_set_capability(dev, EV_FF, FF_RUMBLE);
+		error = input_ff_create_memless(dev, NULL, uinput_play_effect);
+		if (error)
+			goto fail1;
+	} else if (udev->ff_effects_max) {
  		error = input_ff_create(dev, udev->ff_effects_max);
  		if (error)
  			goto fail1;
@@ -806,7 +823,11 @@  static long uinput_ioctl_handler(struct
  			goto out;

  		case UI_DEV_CREATE:
-			retval = uinput_create_device(udev);
+			retval = uinput_create_device(udev, 0);
+			goto out;
+
+		case UI_DEV_CREATE_MEMLESS:
+			retval = uinput_create_device(udev, 1);
  			goto out;

  		case UI_DEV_DESTROY:
diff -uprN a/include/uapi/linux/uinput.h b/include/uapi/linux/uinput.h
--- a/include/uapi/linux/uinput.h	2016-05-08 11:45:02.451934943 +0200
+++ b/include/uapi/linux/uinput.h	2016-05-08 18:05:56.344937754 +0200
@@ -219,6 +219,10 @@  struct uinput_abs_setup {
  #define UI_FF_UPLOAD		1
  #define UI_FF_ERASE		2

+/* Memless devices support */
+#define UI_DEV_CREATE_MEMLESS _IO(UINPUT_IOCTL_BASE, 5)
+#define EV_UINPUT_MEMLESS		(EV_UINPUT + 1)
+
  struct uinput_user_dev {
  	char name[UINPUT_MAX_NAME_SIZE];
  	struct input_id id;