You are not logged in.
I use a Lenovo TrackPoint Keyboard II over bluetooth. It supports a fn_lock sysfs attribute that controls whether the Fn row acts as F1–F12 or as media keys.
/sys/bus/hid/devices/0005:17EF:60E1.*/fn_lockI prefer FnLock off, so I used the following udev rule to set that automatically when the keyboard connects:
ACTION=="add", SUBSYSTEM=="hid", ENV{HID_ID}=="0005:000017EF:000060E1", ATTR{fn_lock}="0"This worked until recently, when I updated my system, including a newer kernel version. After the update, the fn_lock attribute still exists, but is created shortly after the "add" udev event. When the rule fired, fn_lock did not yet exist, so setting it with ATTR did nothing.
To confirm this, I temporarily changed ATTR{fn_lock}="0" to a debugging RUN command:
RUN+="/bin/sh -c 'ls %S%p >> /home/ivan/udev-debug.txt; sleep 0.5; ls %S%p >> /home/ivan/udev-debug.txt'"The first ls showed no fn_lock; the second (after a short delay) did.
So my fix was to use a RUN+= command and delay briefly so the write occurs after the attribute appears:
ACTION=="add", SUBSYSTEM=="hid", ENV{HID_ID}=="0005:000017EF:000060E1", \
RUN+="/bin/sh -c 'sleep 0.05; echo 0 > %S%p/fn_lock'"Is there a recommended way to run a follow-up action after all attributes are created?
Is there a better synchronization point for hid-lenovo devices (e.g., a different udev event, or waiting for a specific attribute)?
Would bind/unbind rules or change events be more appropriate here?
UPDATE: 2025-11-17
Solution: Matching a "bind" event instead of "add" fixed this, so my updated udev rule is:
ACTION=="bind", SUBSYSTEM=="hid", ENV{HID_ID}=="0005:000017EF:000060E1", ATTR{fn_lock}="0"
Last edited by ivanbrennan (2025-11-17 13:06:23)
Offline
This commit to the kernel looks sligtly related: https://github.com/torvalds/linux/commi … f670ed88b6
But this shouldn't lead to RUN+= execution before attributes created. If that's true, something is fundamentally broken either in the kernel or in systemd. A lot of udev rules rely on attributes creation atomicity.
This worked until recently, when I updated my system, including a newer kernel version.
Could you identify which package update causes the behavior change? Likely it is linux or systemd, try to downgrade both and update one by one.
Also logs from udev could be helpful. You can increace udev logs verbosity by placing "udev_log=debug" to /etc/udev/udev.conf or by running "udevadm control -l debug".
Last edited by dimich (2025-11-11 16:05:35)
Offline
Welcome to the forum, ivanbrennan.
Assuming this is not a bug in kernel, check if the device has more specific matches later. As devices are recognized by the kernel, they go through multiple matches. If one tries to match against a too generic one, that may happen too early.
As an example my USB mouse, upon being added, is matched by “pci”, then “usb”, “hid”, and then finally “input” subsystems. If I’d wish to modify its properties as an input device, I’d match against SUBSYSTEM=="input" and not SUBSYSTEM=="usb". Despite the latter already knows the VID:PID pair.
Adding a delay to the command executed by Udev is a bad idea. Per man 7 udev:
This can only be used for very short-running foreground tasks. Running an event process for a long period of time may block all further events for this or a dependent device.
Paperclips in avatars? | Sometimes I seem a bit harsh — don’t get offended too easily!
Offline
Thank you both for your help on this.
Could you identify which package update causes the behavior change? Likely it is linux or systemd, try to downgrade both and update one by one.
I downgraded, then tried different versions of the kernel and of systemd, and though I wasn't able to identify the version(s) where the behavior changed (switching systemd versions was kind of a rough ride), it seemed to depend on the systemd version rather than that of the kernel.
...check if the device has more specific matches later.
This set me in the right direction. Running `udevadm monitor`, when I turned on the keyboard, I noticed a bind event later in the sequence of events, so I adjusted my udev rule to match on that, and it seems to have done the trick.
ACTION=="bind", SUBSYSTEM=="hid", ENV{HID_ID}=="0005:000017EF:000060E1", ATTR{fn_lock}="0"Offline
check if the device has more specific matches later. … seems to have done the trick
\o/
Please always remember to mark resolved threads by editing your initial posts subject - so others will know that there's no task left, but maybe a solution to find.
Thanks.
Offline