From 37340ac2c7be914ff76fdc6bb505b204a4140268 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 21 May 2026 18:50:39 -0700 Subject: Input: userio - update maintainer name She's been committing under the name Lyude Paul for a while Signed-off-by: Vicki Pfau Link: https://patch.msgid.link/20260522015040.3953472-1-vi@endrift.com Signed-off-by: Dmitry Torokhov --- include/uapi/linux/userio.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/uapi/linux/userio.h b/include/uapi/linux/userio.h index 74c9951d2cd0..98fe7e9089c4 100644 --- a/include/uapi/linux/userio.h +++ b/include/uapi/linux/userio.h @@ -2,7 +2,7 @@ /* * userio: virtual serio device support * Copyright (C) 2015 Red Hat - * Copyright (C) 2015 Lyude (Stephen Chandler Paul) + * Copyright (C) 2015 Lyude Paul * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the -- cgit From c6f1363abbff69e5bd1cd1fcf060e1510e8d6d31 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 21 May 2026 18:50:40 -0700 Subject: Input: userio - allow setting other id values Previously, only the type value was settable. The proto value is used internally for choosing the right drivers, so we should expose it. The other values make sense to expose as well. Signed-off-by: Vicki Pfau Link: https://patch.msgid.link/20260522015040.3953472-2-vi@endrift.com Signed-off-by: Dmitry Torokhov --- Documentation/input/userio.rst | 23 +++++++++++++++++++++-- drivers/input/serio/userio.c | 30 ++++++++++++++++++++++++++++++ include/uapi/linux/userio.h | 5 ++++- 3 files changed, 55 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/input/userio.rst b/Documentation/input/userio.rst index 415962152815..7aaaa629bde0 100644 --- a/Documentation/input/userio.rst +++ b/Documentation/input/userio.rst @@ -66,8 +66,27 @@ USERIO_CMD_SET_PORT_TYPE ~~~~~~~~~~~~~~~~~~~~~~~~ Sets the type of port we're emulating, where ``data`` is the port type being -set. Can be any of the macros from . For example: SERIO_8042 -would set the port type to be a normal PS/2 port. +set. Can be any of the serio type macros from . For example: +SERIO_8042 would set the port type to be a normal PS/2 port. + +USERIO_CMD_SET_PORT_PROTO +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sets the protocol of port we're emulating, where ``data`` is the protocol being +set. Can be any of the serio proto macros from . For example: +SERIO_IFORCE would set the port type to be an I-Force serial joystick. + +USERIO_CMD_SET_PORT_ID +~~~~~~~~~~~~~~~~~~~~~~ + +Sets the ``id`` value on the identification of port we're emulating, where +``data`` is the value being set. + +USERIO_CMD_SET_PORT_EXTRA +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sets the ``extra`` value on the identification of port we're emulating, where +``data`` is the value being set. USERIO_CMD_SEND_INTERRUPT ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c index abca8cb6aca5..8c19975c84bf 100644 --- a/drivers/input/serio/userio.c +++ b/drivers/input/serio/userio.c @@ -206,6 +206,36 @@ static int userio_execute_cmd(struct userio_device *userio, userio->serio->id.type = cmd->data; break; + case USERIO_CMD_SET_PORT_EXTRA: + if (userio->running) { + dev_warn(userio_misc.this_device, + "Can't change port extra on an already running userio instance\n"); + return -EBUSY; + } + + userio->serio->id.extra = cmd->data; + break; + + case USERIO_CMD_SET_PORT_ID: + if (userio->running) { + dev_warn(userio_misc.this_device, + "Can't change port id on an already running userio instance\n"); + return -EBUSY; + } + + userio->serio->id.id = cmd->data; + break; + + case USERIO_CMD_SET_PORT_PROTO: + if (userio->running) { + dev_warn(userio_misc.this_device, + "Can't change port proto on an already running userio instance\n"); + return -EBUSY; + } + + userio->serio->id.proto = cmd->data; + break; + case USERIO_CMD_SEND_INTERRUPT: if (!userio->running) { dev_warn(userio_misc.this_device, diff --git a/include/uapi/linux/userio.h b/include/uapi/linux/userio.h index 98fe7e9089c4..550c7465af1f 100644 --- a/include/uapi/linux/userio.h +++ b/include/uapi/linux/userio.h @@ -27,7 +27,10 @@ enum userio_cmd_type { USERIO_CMD_REGISTER = 0, USERIO_CMD_SET_PORT_TYPE = 1, - USERIO_CMD_SEND_INTERRUPT = 2 + USERIO_CMD_SEND_INTERRUPT = 2, + USERIO_CMD_SET_PORT_EXTRA = 3, + USERIO_CMD_SET_PORT_ID = 4, + USERIO_CMD_SET_PORT_PROTO = 5, }; /* -- cgit From ef166ce08801c5237662868d9ec0331d53a38ece Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Sat, 6 Jun 2026 15:04:20 -0700 Subject: Input: stop force-feedback timer when unregistering input devices Memoryless force-feedback devices use a timer to manage playback of effects. When a driver for such a device is unbound (or the device is unregistered for other reasons), the driver typically frees its private data synchronously. However, the input_dev structure (and its associated force-feedback structures, including the timer) is only freed when the last user closes the corresponding device node. If userspace keeps the device node open while the device is unregistered (e.g., during driver unbind), the force-feedback timer can still fire after the driver's private data has been freed. Introduce a new 'stop' callback to struct ff_device, and call it from input_unregister_device() before the device is deleted. Implement this callback for memoryless devices and synchronously shut down the timer to ensure it is stopped and cannot be rearmed once unregistration happens. Assisted-by: Gemini:gemini-3.1-pro Signed-off-by: Dmitry Torokhov --- drivers/input/ff-memless.c | 27 +++++++++++++++++++++------ drivers/input/input.c | 3 +++ include/linux/input.h | 3 +++ 3 files changed, 27 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index 937370d04928..d1fefd1dfc0d 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c @@ -484,17 +484,31 @@ static void ml_ff_destroy(struct ff_device *ff) struct ml_device *ml = ff->private; /* - * Even though we stop all playing effects when tearing down - * an input device (via input_device_flush() that calls into - * input_ff_flush() that stops and erases all effects), we - * do not actually stop the timer, and therefore we should - * do it here. + * The timer is normally shut down in ml_ff_stop() when the device + * is unregistered. However, we still shut it down here as a safety + * net and for cases where the device was never registered (e.g. + * error paths during probe). */ - timer_delete_sync(&ml->timer); + timer_shutdown_sync(&ml->timer); kfree(ml->private); } +static void ml_ff_stop(struct ff_device *ff) +{ + struct ml_device *ml = ff->private; + + /* + * Even though we stop all playing effects when tearing down an + * input device (by the way of evdev calling input_flush_device() + * that calls into input_ff_flush() that stops and erases all + * effects), we do not actually shutdown the timer, and therefore + * we should do it here to prevent it firing after the input + * device is unregistered and its associated resources are freed. + */ + timer_shutdown_sync(&ml->timer); +} + /** * input_ff_create_memless() - create memoryless force-feedback device * @dev: input device supporting force-feedback @@ -529,6 +543,7 @@ int input_ff_create_memless(struct input_dev *dev, void *data, ff->playback = ml_ff_playback; ff->set_gain = ml_ff_set_gain; ff->destroy = ml_ff_destroy; + ff->stop = ml_ff_stop; /* we can emulate periodic effects with RUMBLE */ if (test_bit(FF_RUMBLE, ff->ffbit)) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 39d9d2b1e3ca..cf6fecea79b8 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -2212,6 +2212,9 @@ static void __input_unregister_device(struct input_dev *dev) input_wakeup_procfs_readers(); } + if (dev->ff && dev->ff->stop) + dev->ff->stop(dev->ff); + device_del(&dev->dev); } diff --git a/include/linux/input.h b/include/linux/input.h index 06ca62328db1..3022bb730898 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -543,6 +543,8 @@ extern const struct class input_class; * @set_autocenter: Called to auto-center device * @destroy: called by input core when parent input device is being * destroyed + * @stop: called by input core when parent input device is being + * unregistered * @private: driver-specific data, will be freed automatically * @ffbit: bitmap of force feedback capabilities truly supported by * device (not emulated like ones in input_dev->ffbit) @@ -571,6 +573,7 @@ struct ff_device { void (*set_autocenter)(struct input_dev *dev, u16 magnitude); void (*destroy)(struct ff_device *); + void (*stop)(struct ff_device *); void *private; -- cgit