diff --git a/bin/omarchy-haptic-touchpad b/bin/omarchy-haptic-touchpad deleted file mode 100755 index a98bd90a..00000000 --- a/bin/omarchy-haptic-touchpad +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python3 - -# omarchy:summary=Run the Synaptics touchpad haptic feedback daemon - -"""Haptic feedback daemon for Synaptics touchpads with Manual Trigger. - -Monitors touchpad button press events and sends haptic pulses via HID -feature reports. Required because the kernel's HID haptic subsystem only -supports Auto Trigger with waveform enumeration, not the simpler Manual -Trigger protocol used by these Synaptics touchpads. -""" - -import fcntl, glob, os, struct, sys - -VENDOR = "06CB" -REPORT_ID = 0x37 -INTENSITY = 40 # 0-100 - -# input_event: struct timeval (16 bytes on 64-bit) + type(H) + code(H) + value(i) -EVENT_FORMAT = "llHHi" -EVENT_SIZE = struct.calcsize(EVENT_FORMAT) -EV_KEY = 0x01 -BTN_LEFT = 272 -BTN_RIGHT = 273 -BTN_MIDDLE = 274 - -# ioctl: HIDIOCSFEATURE(len) = _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) -def HIDIOCSFEATURE(length): - return 0xC0000000 | (length << 16) | (ord("H") << 8) | 0x06 - - -def find_hidraw(): - for path in sorted(glob.glob("/sys/class/hidraw/hidraw*")): - uevent = os.path.join(path, "device", "uevent") - try: - with open(uevent) as f: - content = f.read().upper() - if f"0000{VENDOR}" in content: - return os.path.join("/dev", os.path.basename(path)) - except OSError: - continue - return None - - -def find_touchpad_event(): - for path in sorted(glob.glob("/sys/class/input/event*/device/name")): - try: - with open(path) as f: - name = f.read().strip().upper() - if VENDOR in name and "TOUCHPAD" in name: - event = path.split("/")[-3] - return os.path.join("/dev/input", event) - except OSError: - continue - return None - - -def main(): - hidraw = find_hidraw() - if not hidraw: - print("No Synaptics haptic touchpad hidraw device found", file=sys.stderr) - sys.exit(1) - - event = find_touchpad_event() - if not event: - print("No Synaptics haptic touchpad input device found", file=sys.stderr) - sys.exit(1) - - print(f"Haptic touchpad: hidraw={hidraw} input={event} intensity={INTENSITY}", flush=True) - - haptic_report = struct.pack("BB", REPORT_ID, INTENSITY) - ioctl_req = HIDIOCSFEATURE(len(haptic_report)) - - hidraw_fd = os.open(hidraw, os.O_RDWR) - event_fd = os.open(event, os.O_RDONLY) - - try: - while True: - data = os.read(event_fd, EVENT_SIZE) - if len(data) < EVENT_SIZE: - continue - _, _, ev_type, code, value = struct.unpack(EVENT_FORMAT, data) - if ev_type == EV_KEY and code in (BTN_LEFT, BTN_RIGHT, BTN_MIDDLE) and value == 1: - try: - fcntl.ioctl(hidraw_fd, ioctl_req, haptic_report) - except OSError: - pass - except KeyboardInterrupt: - pass - finally: - os.close(event_fd) - os.close(hidraw_fd) - - -if __name__ == "__main__": - main() diff --git a/bin/omarchy-hw-dell-xps-haptic-touchpad b/bin/omarchy-hw-dell-xps-haptic-touchpad new file mode 100755 index 00000000..cc0e5a62 --- /dev/null +++ b/bin/omarchy-hw-dell-xps-haptic-touchpad @@ -0,0 +1,5 @@ +#!/bin/bash + +# omarchy:summary=Match Dell XPS systems with the Synaptics haptic touchpad. + +omarchy-hw-match "XPS" && [[ -e /sys/bus/i2c/devices/i2c-VEN_06CB:00 ]] diff --git a/bin/omarchy-menu b/bin/omarchy-menu index 38a27ae1..9f098c92 100755 --- a/bin/omarchy-menu +++ b/bin/omarchy-menu @@ -233,13 +233,18 @@ show_hardware_menu() { options="$options\n󰟸 Touchpad" fi + if omarchy-hw-dell-xps-haptic-touchpad && omarchy-cmd-present dell-xps-touchpad-haptics; then + options="$options\n󰌌 Touchpad Haptics" + fi + if omarchy-hw-touchscreen; then options="$options\n󰆽 Touchscreen" fi case $(menu "Toggle" "$options") in *Laptop*) omarchy-hyprland-monitor-internal toggle ;; - *Mirror*) omarchy-hyprland-monitor-internal-mirror toggle;; + *Mirror*) omarchy-hyprland-monitor-internal-mirror toggle ;; + *Haptics*) show_hardware_touchpad_haptics_menu ;; *Touchpad*) omarchy-toggle-touchpad ;; *Touchscreen*) omarchy-toggle-touchscreen ;; *"Hybrid GPU"*) present_terminal omarchy-toggle-hybrid-gpu ;; @@ -247,6 +252,17 @@ show_hardware_menu() { esac } +show_hardware_touchpad_haptics_menu() { + local current=$(dell-xps-touchpad-haptics get) + local selected=$(menu "Touchpad Haptics" "low\nmid\nhigh" "" "$current") + + if [[ -n $selected ]]; then + dell-xps-touchpad-haptics set "$selected" + else + back_to show_hardware_menu + fi +} + show_style_menu() { case $(menu "Style" "󰸌 Theme\n󰟵 Unlock\n Font\n Background\n Hyprland\n󱄄 Screensaver\n About") in *Theme*) show_theme_menu ;; diff --git a/install/config/all.sh b/install/config/all.sh index 72effc32..9938570a 100644 --- a/install/config/all.sh +++ b/install/config/all.sh @@ -50,8 +50,6 @@ run_logged $OMARCHY_INSTALL/config/hardware/intel/fred.sh run_logged $OMARCHY_INSTALL/config/hardware/intel/fix-wifi7-eht.sh run_logged $OMARCHY_INSTALL/config/hardware/intel/sof-firmware.sh -run_logged $OMARCHY_INSTALL/config/hardware/dell/fix-xps-haptic-touchpad.sh - run_logged $OMARCHY_INSTALL/config/hardware/asus/fix-asus-ptl-display-backlight.sh run_logged $OMARCHY_INSTALL/config/hardware/asus/fix-asus-ptl-b9406-display.sh run_logged $OMARCHY_INSTALL/config/hardware/asus/fix-asus-ptl-b9406-touchpad.sh diff --git a/install/config/hardware/dell/fix-xps-haptic-touchpad.sh b/install/config/hardware/dell/fix-xps-haptic-touchpad.sh deleted file mode 100644 index dd079611..00000000 --- a/install/config/hardware/dell/fix-xps-haptic-touchpad.sh +++ /dev/null @@ -1,36 +0,0 @@ -# Fix Dell XPS haptic touchpad. -# The Synaptics haptic touchpad (vendor 06CB) uses the HID Manual Trigger -# protocol, but the kernel's HID haptic subsystem only supports Auto Trigger. -# This sets up a lightweight daemon that monitors touchpad button events and -# sends haptic pulses via HID feature reports on the hidraw device. -# Also disables I2C runtime PM to prevent the haptic engine losing state -# across suspend/resume. - -if omarchy-hw-match "XPS" \ - && ls /sys/bus/i2c/devices/i2c-VEN_06CB:00 2>/dev/null; then - - # Keep I2C controller power on to prevent haptic engine losing state - sudo tee /etc/udev/rules.d/99-dell-xps-haptic-touchpad.rules << 'EOF' -ACTION=="add", SUBSYSTEM=="pci", KERNEL=="0000:00:19.0", ATTR{power/control}="on" -ACTION=="add", SUBSYSTEM=="platform", KERNEL=="i2c_designware.0", ATTR{power/control}="on" -EOF - sudo udevadm control --reload-rules - - # Haptic feedback daemon as a systemd service - sudo tee /etc/systemd/system/dell-xps-haptic-touchpad.service << SVC -[Unit] -Description=Dell XPS haptic touchpad feedback -After=systemd-udev-settle.service - -[Service] -Type=simple -ExecStart=$OMARCHY_PATH/bin/omarchy-haptic-touchpad -Restart=on-failure -RestartSec=2 - -[Install] -WantedBy=multi-user.target -SVC - sudo systemctl daemon-reload - sudo systemctl enable dell-xps-haptic-touchpad.service -fi diff --git a/install/omarchy-other.packages b/install/omarchy-other.packages index e5f88998..56f7c555 100644 --- a/install/omarchy-other.packages +++ b/install/omarchy-other.packages @@ -61,6 +61,9 @@ vulkan-asahi # Surface laptop support packages linux-firmware-marvell +# Dell laptop support packages +dell-xps-touchpad-haptics + # T2 MacBook support packages apple-bcm-firmware apple-t2-audio-config diff --git a/install/packaging/all.sh b/install/packaging/all.sh index 4419e23a..d1db1b91 100644 --- a/install/packaging/all.sh +++ b/install/packaging/all.sh @@ -7,4 +7,5 @@ run_logged $OMARCHY_INSTALL/packaging/tuis.sh run_logged $OMARCHY_INSTALL/packaging/npx.sh run_logged $OMARCHY_INSTALL/packaging/asus-rog.sh run_logged $OMARCHY_INSTALL/packaging/framework16.sh +run_logged $OMARCHY_INSTALL/packaging/dell-xps-touchpad-haptics.sh run_logged $OMARCHY_INSTALL/packaging/surface.sh diff --git a/install/packaging/dell-xps-touchpad-haptics.sh b/install/packaging/dell-xps-touchpad-haptics.sh new file mode 100755 index 00000000..09ec5d95 --- /dev/null +++ b/install/packaging/dell-xps-touchpad-haptics.sh @@ -0,0 +1,3 @@ +if omarchy-hw-dell-xps-haptic-touchpad; then + omarchy-pkg-add dell-xps-touchpad-haptics +fi diff --git a/migrations/1777653181.sh b/migrations/1777653181.sh new file mode 100644 index 00000000..e79c782b --- /dev/null +++ b/migrations/1777653181.sh @@ -0,0 +1,14 @@ +echo "Move Dell XPS touchpad haptics into the packaged service" + +if omarchy-hw-dell-xps-haptic-touchpad; then + sudo systemctl disable --now dell-xps-haptic-touchpad.service 2>/dev/null || true + sudo rm -f /etc/systemd/system/dell-xps-haptic-touchpad.service + sudo rm -f /etc/systemd/system/multi-user.target.wants/dell-xps-haptic-touchpad.service + sudo rm -rf /etc/systemd/system/dell-xps-haptic-touchpad.service.d + sudo rm -f /etc/udev/rules.d/99-dell-xps-haptic-touchpad.rules + sudo rm -f /etc/omarchy-dell-haptic-touchpad.env + sudo systemctl daemon-reload + sudo udevadm control --reload-rules + + source "$OMARCHY_PATH/install/packaging/dell-xps-touchpad-haptics.sh" +fi