From 1f1e67911c5320fe5c36a0334144239b860825a9 Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:11:58 +0200 Subject: [PATCH 1/9] Update Valve Index reboot rules for systemd service --- src/99-valve-index-reboot.rules | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/99-valve-index-reboot.rules b/src/99-valve-index-reboot.rules index cbf3dff..eb67750 100644 --- a/src/99-valve-index-reboot.rules +++ b/src/99-valve-index-reboot.rules @@ -1,6 +1,6 @@ # Valve Index HMD: fix blank EDID -# Works around blank EDID bug that makes the kernel see the HMD as a 640x480 monitor. -# Sends a HID reboot command once per boot when the device is enumerated. -# /tmp is cleared on boot so the flag resets automatically. +# Trigger systemd service on device add. -KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2300", ACTION=="add", RUN+="/bin/sh -c '(sleep 2; test -f /tmp/.valve-index-rebooted || { printf \"\\x16\\x01\" | cat - /dev/zero | head -c 64 > /dev/%k && touch /tmp/.valve-index-rebooted; }) &'" +ACTION=="add", SUBSYSTEM=="hidraw", KERNEL=="hidraw*", \ + ATTRS{idVendor}=="28de", ATTRS{idProduct}=="2300", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}+="valve-index-hid-reboot@%k.service" From 49b46a19bcdd118a32232418c1be09c0894e037a Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:13:00 +0200 Subject: [PATCH 2/9] Add script to reboot Valve Index HID device --- src/valve-index-hid-reboot.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/valve-index-hid-reboot.sh diff --git a/src/valve-index-hid-reboot.sh b/src/valve-index-hid-reboot.sh new file mode 100644 index 0000000..d3d435c --- /dev/null +++ b/src/valve-index-hid-reboot.sh @@ -0,0 +1,24 @@ +#!/bin/sh +set -eu + +VID="28de" +PID="2300" +FLAG="/run/.valve-index-rebooted" + +for dev in /dev/hidraw*; do + [ -e "$dev" ] || continue + sys="/sys/class/hidraw/$(basename "$dev")/device" + + v="$(cat "$sys/idVendor" 2>/dev/null || true)" + p="$(cat "$sys/idProduct" 2>/dev/null || true)" + v="${v#0x}" + p="${p#0x}" + + if [ "$v" = "$VID" ] && [ "$p" = "$PID" ]; then + printf '\x16\x01' | cat - /dev/zero | head -c 64 > "$dev" || true + : > "$FLAG" + exit 0 + fi +done + +exit 0 From 09c6407c563fb3e04d49888e7898fa92e6ae2e98 Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:13:42 +0200 Subject: [PATCH 3/9] Add systemd service for Valve Index HID reboot --- src/valve-index-hid-reboot@.service | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/valve-index-hid-reboot@.service diff --git a/src/valve-index-hid-reboot@.service b/src/valve-index-hid-reboot@.service new file mode 100644 index 0000000..1f097d7 --- /dev/null +++ b/src/valve-index-hid-reboot@.service @@ -0,0 +1,8 @@ +[Unit] +Description=Valve Index HID reboot for /dev/%I +After=systemd-udevd.service +ConditionPathExists=/dev/%I + +[Service] +Type=oneshot +ExecStart=/bin/sh -c 'sleep 2; if ! test -f /run/.valve-index-rebooted; then /usr/local/sbin/valve-index-hid-reboot.sh; fi' From b8090daa38c5109b3c88cac1c7b9aac3b1184632 Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:15:00 +0200 Subject: [PATCH 4/9] Add valve-index-hid-reboot script for post-reboot actions --- src/valve-index-hid-reboot | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/valve-index-hid-reboot diff --git a/src/valve-index-hid-reboot b/src/valve-index-hid-reboot new file mode 100644 index 0000000..5555747 --- /dev/null +++ b/src/valve-index-hid-reboot @@ -0,0 +1,8 @@ +#!/bin/sh +case "$1" in + post) + rm -f /run/.valve-index-rebooted + sleep 2 + /usr/local/sbin/valve-index-hid-reboot.sh + ;; +esac From 34423e30ce020779118f049e6bb07c00e2940f57 Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:17:47 +0200 Subject: [PATCH 5/9] Enhance install.sh for better file management Refactor install script to support multiple files and improve download handling. --- src/install.sh | 79 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 27 deletions(-) diff --git a/src/install.sh b/src/install.sh index 17ef012..5154cb8 100755 --- a/src/install.sh +++ b/src/install.sh @@ -7,8 +7,21 @@ set -euo pipefail # Config # --------------------------------------------------------------------------- RULE_FILE="99-valve-index-reboot.rules" +SCRIPT_FILE="valve-index-hid-reboot.sh" +SERVICE_FILE="valve-index-hid-reboot@.service" +HOOK_FILE="valve-index-hid-reboot" + RULE_DST="/etc/udev/rules.d/$RULE_FILE" -RULE_RAW_URL="https://raw.githubusercontent.com/MiguVT/fixvr/main/src/$RULE_FILE" +SCRIPT_DST="/usr/local/sbin/$SCRIPT_FILE" +SERVICE_DST="/etc/systemd/system/$SERVICE_FILE" +HOOK_DST="/etc/systemd/system-sleep/$HOOK_FILE" # Universal, distro-agnostic + +RAW_BASE="https://raw.githubusercontent.com/MiguVT/fixvr/main/src" +RULE_RAW_URL="$RAW_BASE/$RULE_FILE" +SCRIPT_RAW_URL="$RAW_BASE/$SCRIPT_FILE" +SERVICE_RAW_URL="$RAW_BASE/$SERVICE_FILE" +HOOK_RAW_URL="$RAW_BASE/$HOOK_FILE" + AUR_PKG="fixvr-git" # --------------------------------------------------------------------------- @@ -40,17 +53,19 @@ setup_sudo() { fi } -# Locate the rule file relative to this script (works when called from anywhere) -# Falls back to downloading from GitHub when run via curl | bash -find_rule_file() { +# Locate a file relative to this script, fallback to download from GitHub +find_or_download() { + local filename="$1" + local url="$2" + local script_dir script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" local candidates=( - "$script_dir/$RULE_FILE" # running from src/ - "$script_dir/../src/$RULE_FILE" # running from repo root - "$(pwd)/src/$RULE_FILE" # cwd is repo root - "$(pwd)/$RULE_FILE" # cwd is src/ + "$script_dir/$filename" # running from src/ + "$script_dir/../src/$filename" # running from repo root + "$(pwd)/src/$filename" # cwd is repo root + "$(pwd)/$filename" # cwd is src/ ) for f in "${candidates[@]}"; do @@ -60,21 +75,20 @@ find_rule_file() { fi done - # Not found locally (e.g. run via curl | bash) — download from GitHub - warn "Rule file not found locally, downloading from GitHub…" >&2 - local tmp_rule - tmp_rule="$(mktemp "/tmp/${RULE_FILE}.XXXXXX")" + warn "File $filename not found locally, downloading from GitHub…" >&2 + local tmp_file + tmp_file="$(mktemp "/tmp/${filename}.XXXXXX")" if command -v curl &>/dev/null; then - curl -fsSL "$RULE_RAW_URL" -o "$tmp_rule" || die "Failed to download rule file from GitHub." + curl -fsSL "$url" -o "$tmp_file" || die "Failed to download $filename." elif command -v wget &>/dev/null; then - wget -qO "$tmp_rule" "$RULE_RAW_URL" || die "Failed to download rule file from GitHub." + wget -qO "$tmp_file" "$url" || die "Failed to download $filename." else - die "Rule file not found locally and neither curl nor wget is available." + die "Neither curl nor wget is available to download $filename." fi - [[ -s "$tmp_rule" ]] || die "Downloaded rule file is empty." - printf '%s\n' "$tmp_rule" + [[ -s "$tmp_file" ]] || die "Downloaded $filename is empty." + printf '%s\n' "$tmp_file" } # --------------------------------------------------------------------------- @@ -164,12 +178,12 @@ install_aur() { info "Using AUR helper: $aur_helper" step "Installing $AUR_PKG…" - + # When piped via `curl | bash`, standard input is hijacked. # We must explicitly reconnect stdin to the terminal so the user can interact. "$aur_helper" -S "$AUR_PKG" Date: Tue, 5 May 2026 13:25:52 +0200 Subject: [PATCH 6/9] Only create flag if write succeed Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/valve-index-hid-reboot.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/valve-index-hid-reboot.sh b/src/valve-index-hid-reboot.sh index d3d435c..30d843b 100644 --- a/src/valve-index-hid-reboot.sh +++ b/src/valve-index-hid-reboot.sh @@ -15,9 +15,13 @@ for dev in /dev/hidraw*; do p="${p#0x}" if [ "$v" = "$VID" ] && [ "$p" = "$PID" ]; then - printf '\x16\x01' | cat - /dev/zero | head -c 64 > "$dev" || true - : > "$FLAG" - exit 0 + if printf '\x16\x01' | cat - /dev/zero | head -c 64 > "$dev"; then + : > "$FLAG" + exit 0 + else + echo "Failed to write reboot command to $dev" >&2 + exit 1 + fi fi done From 0dbdf9561b29e04e3b0bf3bfa8537cc65f3a0701 Mon Sep 17 00:00:00 2001 From: MiguVT <71216796+MiguVT@users.noreply.github.com> Date: Tue, 5 May 2026 13:26:52 +0200 Subject: [PATCH 7/9] Use flock for prevent race condition Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/valve-index-hid-reboot@.service | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/valve-index-hid-reboot@.service b/src/valve-index-hid-reboot@.service index 1f097d7..54eba59 100644 --- a/src/valve-index-hid-reboot@.service +++ b/src/valve-index-hid-reboot@.service @@ -5,4 +5,4 @@ ConditionPathExists=/dev/%I [Service] Type=oneshot -ExecStart=/bin/sh -c 'sleep 2; if ! test -f /run/.valve-index-rebooted; then /usr/local/sbin/valve-index-hid-reboot.sh; fi' +ExecStart=/usr/bin/flock /run/valve-index-hid-reboot.lock /bin/sh -c 'sleep 2; if ! test -f /run/.valve-index-rebooted; then /usr/local/sbin/valve-index-hid-reboot.sh; fi' From 15febe98153f3e8fdf502c0048c515fda5c602f7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 11:30:13 +0000 Subject: [PATCH 8/9] cleanup: track and remove tmp files with EXIT trap in find_or_download Agent-Logs-Url: https://github.com/MiguVT/fixvr/sessions/7933e0e5-9995-4c53-be16-711f1d2b279f Co-authored-by: MiguVT <71216796+MiguVT@users.noreply.github.com> --- src/install.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/install.sh b/src/install.sh index 5154cb8..ae37388 100755 --- a/src/install.sh +++ b/src/install.sh @@ -43,6 +43,10 @@ die() { echo -e "${RED}[✗]${NC} $*" >&2; exit 1; } # Helpers # --------------------------------------------------------------------------- SUDO="" +_TMP_FILES=() # tracks temp files downloaded by find_or_download +_cleanup_tmp() { [[ ${#_TMP_FILES[@]} -gt 0 ]] && rm -f "${_TMP_FILES[@]}"; } +trap '_cleanup_tmp' EXIT + setup_sudo() { if [[ $EUID -eq 0 ]]; then SUDO="" @@ -78,6 +82,7 @@ find_or_download() { warn "File $filename not found locally, downloading from GitHub…" >&2 local tmp_file tmp_file="$(mktemp "/tmp/${filename}.XXXXXX")" + _TMP_FILES+=("$tmp_file") if command -v curl &>/dev/null; then curl -fsSL "$url" -o "$tmp_file" || die "Failed to download $filename." From ffefdba11332c80000edde199a16dfe6fe69e71d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 5 May 2026 11:33:09 +0000 Subject: [PATCH 9/9] install_manual: detect systemctl and die early on non-systemd systems Agent-Logs-Url: https://github.com/MiguVT/fixvr/sessions/8d23d6f6-7500-4700-aa66-c67629d20163 Co-authored-by: MiguVT <71216796+MiguVT@users.noreply.github.com> --- src/install.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/install.sh b/src/install.sh index ae37388..e148150 100755 --- a/src/install.sh +++ b/src/install.sh @@ -197,6 +197,10 @@ install_aur() { install_manual() { setup_sudo + if ! command -v systemctl &>/dev/null; then + die "systemd is required for this fix (the udev rule uses SYSTEMD_WANTS).\n Please use a systemd-based distro or install the files manually." + fi + local rule_src script_src service_src hook_src rule_src="$(find_or_download "$RULE_FILE" "$RULE_RAW_URL")" script_src="$(find_or_download "$SCRIPT_FILE" "$SCRIPT_RAW_URL")"