diff --git a/deploy/nixos/hardware/batm3.nix b/deploy/nixos/hardware/batm3.nix index ce8e1fe..a92159e 100644 --- a/deploy/nixos/hardware/batm3.nix +++ b/deploy/nixos/hardware/batm3.nix @@ -12,6 +12,15 @@ timeout = 3; }; + # Pin the 6.6 LTS kernel. The Dell 9030 AIO's eGalax SAW touch panel + # (0eef:0001) works with the usbtouchscreen driver on 6.6 (the known-good + # internal-SATA install runs 6.6.68). On 25.11's default 6.12 kernel this + # old controller regressed: hid-multitouch grabs it and mis-parses the HID + # report ("failed to fetch feature 7", axes read stuck), usbtouchscreen + # refuses it, and touch is unusable regardless of udev/X config. Matching + # douro.nix's per-hardware kernel pin. Re-test touch before bumping this. + kernelPackages = pkgs.linuxPackages_6_6; + initrd.availableKernelModules = [ "xhci_pci" "ahci" @@ -122,10 +131,20 @@ ''; # eGalax touchscreen (Dell 9030 AIO built-in panel) - # The eGalax HID descriptor confuses libinput (treats it as touchpad). - # Fix: unbind from usbhid at boot, bind to usbtouchscreen kernel module, - # then apply calibration matrix after X11 starts. - # Unbind eGalax from usbhid, bind to usbtouchscreen + # By default usbhid/hid-multitouch claim the eGalax and mis-parse its + # HID report descriptor (X axis reads as stuck), so touch is unusable. + # Fix: hand the device to the usbtouchscreen kernel driver, which parses + # the raw eGalax protocol into a clean single-touch ABS device that the + # X evdev driver + calibration matrix (below) map correctly. This mirrors + # the known-good internal-SATA install. + # + # The RUN command modprobes usbtouchscreen ITSELF before unbinding usbhid + # and handing over via new_id. usbtouchscreen is also in boot.kernelModules + # (systemd-modules-load), but on a USB boot systemd-udev-trigger fires this + # rule (~2s) BEFORE modules-load gets usbtouchscreen in (~12s) — so the + # new_id write hit a not-yet-loaded driver and the panel was left bound to + # nothing. Loading it inline here makes the handoff independent of that + # boot-ordering race (on internal-SATA boot the order happened to work). services.udev.extraRules = lib.mkAfter '' KERNEL=="ttyS[0-9]*", MODE="0666" KERNEL=="ttyUSB[0-9]*", MODE="0666" @@ -133,7 +152,25 @@ SUBSYSTEM=="tty", ATTRS{serial}=="DDDLb103Y23", SYMLINK+="ttyF56", MODE="0666" SUBSYSTEM=="tty", ATTRS{serial}=="A9YW78OC", SYMLINK+="ttyMEI", MODE="0666" SUBSYSTEM=="tty", ATTRS{serial}=="A9ZF8ELY", SYMLINK+="ttyNFC", MODE="0666" - ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0eef", ATTRS{idProduct}=="0001", RUN+="${pkgs.bash}/bin/bash -c 'echo ''$kernel:1.0 > /sys/bus/usb/drivers/usbhid/unbind 2>/dev/null; echo 0eef 0001 > /sys/bus/usb/drivers/usbtouchscreen/new_id 2>/dev/null'" + ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0eef", ATTRS{idProduct}=="0001", RUN+="${pkgs.bash}/bin/bash -c '${pkgs.kmod}/bin/modprobe usbtouchscreen 2>/dev/null; echo ''$kernel:1.0 > /sys/bus/usb/drivers/usbhid/unbind 2>/dev/null; echo 0eef 0001 > /sys/bus/usb/drivers/usbtouchscreen/new_id 2>/dev/null'" + ''; + + # Force the X evdev driver on the eGalax (not libinput). The usbtouchscreen + # node is a plain single-touch absolute device; evdev + the transformation + # matrix in egalax-calibrate below give correct orientation. Mirrors the + # working internal-SATA install's /etc/X11/xorg.conf.d/99-egalax.conf. + environment.etc."X11/xorg.conf.d/99-egalax.conf".text = '' + Section "InputClass" + Identifier "eGalax Touchscreen" + MatchVendor "0eef" + MatchProduct "0001" + MatchDevicePath "/dev/input/event*" + Driver "evdev" + Option "InvertY" "false" + Option "InvertX" "false" + Option "SwapAxes" "false" + Option "Calibration" "" + EndSection ''; # Apply touchscreen calibration after X11 starts @@ -147,9 +184,26 @@ Type = "oneshot"; RemainAfterExit = true; User = "bitspire"; - Environment = "DISPLAY=:0"; - ExecStartPre = "${pkgs.coreutils}/bin/sleep 3"; - ExecStart = "${pkgs.xorg.xinput}/bin/xinput set-prop 'eGalax Inc. USB TouchController' 'Coordinate Transformation Matrix' 0 -1.268 1.147 -1.224 0 1.118 0 0 1"; + # DISPLAY *and* XAUTHORITY — without the auth cookie xinput dies with + # "Invalid MIT-MAGIC-COOKIE-1 key / Unable to connect to X server" and + # the matrix is never applied, so touches register but land in the wrong + # place (the panel then feels dead). This was the actual boot-time bug. + Environment = [ "DISPLAY=:0" "XAUTHORITY=/home/bitspire/.Xauthority" ]; + # Wait for the eGalax X device to appear (usbtouchscreen binds a little + # after display-manager on a USB boot) and retry, instead of a fixed + # sleep — more robust to boot timing. Matrix: swap X/Y + invert + scale + # to the active panel area (matches the known-good internal install). + ExecStart = pkgs.writeShellScript "egalax-calibrate" '' + for i in $(${pkgs.coreutils}/bin/seq 1 30); do + if ${pkgs.xorg.xinput}/bin/xinput list --name-only 2>/dev/null | ${pkgs.gnugrep}/bin/grep -qx 'eGalax Inc. USB TouchController'; then + exec ${pkgs.xorg.xinput}/bin/xinput set-prop 'eGalax Inc. USB TouchController' \ + 'Coordinate Transformation Matrix' 0 -1.268 1.147 -1.224 0 1.118 0 0 1 + fi + ${pkgs.coreutils}/bin/sleep 1 + done + echo "egalax-calibrate: eGalax device not found after 30s" >&2 + exit 1 + ''; }; };