Add readonly parameter to InputDevice and writable parameter to list_devices/is_device#251
Open
xz-dev wants to merge 1 commit intogvalkov:mainfrom
Open
Add readonly parameter to InputDevice and writable parameter to list_devices/is_device#251xz-dev wants to merge 1 commit intogvalkov:mainfrom
xz-dev wants to merge 1 commit intogvalkov:mainfrom
Conversation
xz-dev
added a commit
to xz-dev/numlockw
that referenced
this pull request
Apr 1, 2026
Use evdev readonly mode for the status command to prevent O_RDWR open from triggering LED re-assertion on certain hardware (e.g. Tuxedo Stellaris touchpad LED). Temporarily depends on xz-dev/python-evdev@feat/inputdevice-readonly pending upstream merge (gvalkov/python-evdev#251). See: https://www.reddit.com/r/tuxedocomputers/comments/1rtj3c9/
…devices/is_device
0a0b410 to
986ba0f
Compare
xz-dev
added a commit
to xz-dev/numlockw
that referenced
this pull request
Apr 1, 2026
Use evdev readonly mode for the status command to prevent O_RDWR open from triggering LED re-assertion on certain hardware (e.g. Tuxedo Stellaris touchpad LED). Temporarily depends on xz-dev/python-evdev@feat/inputdevice-readonly pending upstream merge (gvalkov/python-evdev#251). See: https://www.reddit.com/r/tuxedocomputers/comments/1rtj3c9/
xz-dev
added a commit
to xz-dev/numlockw
that referenced
this pull request
Apr 1, 2026
…ware Keep evdev device fds permanently open so the kernel never re-triggers driver open callbacks (input_open_device) on subsequent opens. This eliminates LED pulsing caused by repeated open/close cycles on hardware like Tuxedo Stellaris 15 Gen3. See: https://www.reddit.com/r/tuxedocomputers/comments/1rtj3c9/ See: gvalkov/python-evdev#251
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
readonlyparameter toInputDevice.__init__()(readonly=Falseby default, no behavior change)writableparameter tolist_devices()andis_device()(writable=Trueby default, no behavior change)Motivation
Currently
InputDevice.__init__()always attemptsO_RDWRfirst and falls back toO_RDONLYon failure. This has two practical issues:Permission-restricted environments: When a process only has read access to
/dev/input/eventX(common without udev rules or root), theO_RDWRattempt always fails before falling back. Thereadonly=Trueparameter lets callers skip the unnecessary failed syscall.API correctness: Callers that only need to read device state (e.g. querying
leds(),capabilities()) have no way to express "I only need read access" — the constructor always attempts write access regardless of intent.The
writableparameter onlist_devices()/is_device()complements this by allowing enumeration of devices that are readable but not writable.The existing
need_writedecorator onEventIO.write()already guards against writes on read-only fds, so no additional protection is needed.Note on LED pulsing issue
A real-world report described touchpad LED pulsing when polling
InputDevice.leds()at 1–2 Hz. After investigating the Linux kernel source (drivers/input/evdev.c,drivers/input/input.c), the root cause is notO_RDWRvsO_RDONLY— the kernel'sevdev_open()does not distinguish between open modes at all. Both go through the same path:evdev_open()→input_open_device()→dev->open(dev).The actual cause is the repeated open/close cycle itself. Each time the fd is closed,
dev->usersdrops to 0; the next open triggers the hardware driver'sopen()callback again (e.g.hidinput_open()→hid_hw_open()→ USB/I2C transport layer reinitialization), which on certain hardware (Tuxedo Stellaris 15 Gen3) causes the EC firmware to re-assert LED state.The correct fix for the LED pulsing issue is to keep the
InputDevicefd open across queries rather than creating/destroying it each time. TheEVIOCGLEDioctl used byleds()is a pure kernel memory read (bitmap_copy) and does not touch hardware.Changes
src/evdev/device.pyreadonly=Falseto__init__src/evdev/util.pywritable=Truetolist_devices/is_deviceUsage
Relates to #35