tl;dr the non-nixos variant of what I’m trying to put into a nixos-config is:
echo 'SOME:DEVICE:ID:HERE' |
sudo tee /sys/bus/hid/drivers/hid-multitouch/unbind
how would you go about ensuring your nixos state always has just one of the hid-multitouch devices disabled like that, but persistently via nixos config settings? (that is: I don’t want to disable the entire hid-multitouch driver, as that’d break my touchpad).
I’m guessing worst case: nixos must have a generic“run this arbitrary script” solution? I’m not very well versed in nix lang, but willing to learn if someone can point me to what files/objects I need to mutate to pull this off.
This seems like the sort of thing that would go in either a systemd service (for running an arbitrary command) or a udev rule (for the specific case of preventing a particular device from binding in the first place). If you have experience with either of those systems from other distros, you should be able to add one or the other to systemd.services or services.udev.extraRules, respectively. If you’re unfamiliar with both, I’d start learning about udev; that’ll be the most elegant solution for this particular problem.
I’ll figure out how to debug via udevadm test more, since a reboot (after rebuild) revealed the device was back on (maybe my ID_PATH is copy/pasted wrong). Only ever used udev to ensure a drive always mounts to the same path before, but not a “reject device” action like this, so my UDISKS_IGNORE could be wrong too.
If the issue is that the device is being picked up by libinput (I would think so?), try setting ENV{LIBINPUT_IGNORE_DEVICE}="1" in the rule. UDISKS_IGNORE is for, well, disks.
that doc was very helpful, thanks! but I’m still stuck Tried a ton of things, but every reboot I find the device is still bound (still shows up in that /sys/bus/hid/drivers/hid-multitouch folder, and more importantly: libinput still lets its events through).
Of all the variations I’ve tried, these two seem the most likely to be right:
this one (after rebuild, even before reboot) causes udevadm info to at least show the IGNORE attr:
While the second one doesn’t show the IGNORE attr (when I run udevadm info) I do see the IGNORE attr when I run uevadm test /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-2/i2c-ELAN901C:00/0018:04F3:2BB5.0002.
Not sure what else to try, but feels like I must be close and have something silly off someweere… just re-reading those docs and nearby pages now, hoping for something obvious
Hmm. How sure are you that you have the right device path? I would have expected to see more properties than that for a touchscreen.
If you run libinput list-devices, find the Kernel: field corresponding to the touchscreen, and run udevadm test /dev/input/whatever_you_just_found, do you get a different result?
(Also, BTW, udev rules are case-sensitive. When specifying hexadecimal numbers, you have to use lowercase letters! That might be contributing to your second rule not working, though I don’t know if it’ll be sufficient to salvage it; the ID_VENDOR_ID etc. keys might be specific to USB devices, and it looks like your touchscreen is I2C.)
Oh interesting… do you know of a way to verify given my only 100%-certain lead is: the bind/unbind trick? That is… here’s udevadm monitor logs when I temporarily enable/disable:
turning it on for just a few seconds, via the only trick I know (`bind`, `unbind` files)
So to your question: I guess my tiny bit of confident in the path is that: the basename (0018:04F3:2BB5.0002) perfectly matches the string I’ve been using to enable/disable via hid-multitouch folder. I suppose it could be I have to use one of the longer paths? but then, the inputN numbers seem unstable… I picked one at random to manually do an info on anyway nad here’s what I got:
were you expecting to see `ID_INPUT_TOUCHSCREEN` properties like this?
Oh good catch. Fixed, and rebooting/retrying now. Btw IDK that those values are even correct ayway – I just copy/pasted them (guessing wildly) from the HID_NAME device property that udevadm info kept printing: E: HID_NAME=ELAN901C:00 04F3:2BB5
Yes, the output with ID_INPUT=1, ID_INPUT_TOUCHSCREEN=1… that was what I was expecting to see.
So you might have multiple ‘devices’ that are all connected by some sort of master bus, and that master bus has the ‘root’ sysfs path, but it’s the child devices that are actually advertised by udev as the input devices that libinput picks up. In which case, you need to find some stable property or properties that the child device has, and write your udev rule to match those. I’d start with ENV{ID_PATH}=="pci-0000:00:15.1-platform-i2c_designware.1", ENV{ID_INPUT_TOUCHSCREEN}=="1".
I think that worked. I don’t have a good deterministic[1] way to be sure just yet, but for now it seems to be disabled using your matches!
notes for future debuggers: `udevadm info --tree` for a quick dump, to calmly craft your rules
tl;dr validate you’re matching everything by quickly turning on your buggy device, quickly running udevadm info --tree and disabling the device, then calmly crafting your udev rule later.
Rephrasing for future debuggers: you need a rule that matches all child devices not just the one arbitrary (child or root) you first happened upon. Lucky for me I have rhenderic kindly making a perfect suggestion here for a new rule, but in case you need to figure out out on your own, I’m guessing you’ll need to first see all the properties of all the children that you’re trying to match. (I’m guessing you’ll only care about devices that show ID_INPUT_TOUCHSCREEN as suggested, but I’m still experimenting with turning off the hidraw matches too).
Inspecting all the devices’ properties is tricky if you only have seconds (eg: your device is going haywire while the input is still enabled). udevadm info --tree is useful here because it just dumps absolutely everything for you:
$ echo 0018:04F3:2BB5.0002 | sudo tee /sys/bus/hid/drivers/hid-multitouch/bind; \
udevadm info --tree > ~/udevadm-info-tree.utf8.txt; \
echo 0018:04F3:2BB5.0002 | sudo tee /sys/bus/hid/drivers/hid-multitouch/unbind
# note what _your_ device id is (mine was "2BB5.0002"). it can be figured out later
# but it should be some substring of the basename of the buggy device you've
# encountered in hid-multitouch folder
$ less +/2BB5.0002 ~/udevadm-info-tree.utf8.txt
#snipped, but you'll see lots of blocks like this:
P: /devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-2/i2c-ELAN901C:00/0018:04F3:2BB5.0002/input/input41/mouse3
M: mouse3
R: 3
U: input
D: c 13:35
N: input/mouse3
L: 0
E: DEVPATH=/devices/pci0000:00/0000:00:15.1/i2c_designware.1/i2c-2/i2c-ELAN901C:00/0018:04F3:2BB5.0002/input/input41/mouse3
E: SUBSYSTEM=input
E: DEVNAME=/dev/input/mouse3
E: MAJOR=13
E: MINOR=35
E: USEC_INITIALIZED=2383266459
E: PATH=/nix/store/kkvpf4dgsf1q4dfsaxv15bk1aq8a4758-udev-path/bin:/nix/store/kkvpf4dgsf1q4dfsaxv15bk1aq8a4758-udev-path/sbin
E: ID_INPUT=1
E: ID_INPUT_TOUCHSCREEN=1
E: ID_PATH=pci-0000:00:15.1-platform-i2c_designware.1
E: ID_PATH_TAG=pci-0000_00_15_1-platform-i2c_designware_1
#snipped
Indeed in my case absolutely every device listed has the same ID_PATH, so it makes ense that rhendric’s rule works perfectly.
the two ways I have: a) deterministic: check if it’s bound via the hid-multitouch folder (these changes aren’t preventing binding); b) non-deterministic: not get any spurious touch-events (unreliable because sometimes, maybe dependent on screen’s physical temperature, it wouldn’t misfire for about an hour while other times it’d continuously misfire as long as I watched it) ↩︎