mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-10 22:47:02 +01:00
Two levels of pure taxonomy carrying no information, and a 2-directory
cap leaves no room for them. Categories now sit directly under
linux_configuration/: features, fixes, utils, misc, fresh-install,
installers, diagnostics, gaming, boot_recovery, periodic_background, lib,
meta, tests. A script's own lib/ and tests/ are exempt from the cap, so
those stay put.
Depth violations 248 -> 139; roughly 40 of the remainder are inside
digital_wellbeing and hosts, deferred until the guard-lib repoint.
The moves are the easy half. What breaks is every path that counted
levels, and three classes of it had to be found by resolving paths rather
than reading diffs:
- 52 relative `source` lines for lib/common.sh and lib/android.sh. The
correct prefix differs per file: 40 were ../../ and 12 were ../../../,
so a blanket replace would have fixed one set and broken the other.
- REPO_ROOT in 7 fixes/lib/tests harnesses and setup_syncyomi_guard.sh,
each walking up four levels from a directory now two levels shallower.
This caused a real regression -- the fixes suite went red with
"log_warn: command not found" -- caught by running it and comparing
against the pre-move baseline worktree.
- conftest.py's sys.path entries, which took the pytest gate down with
14 collection errors, and the `# shellcheck source=` directives, which
took shellcheck down with SC1091.
16 symlinks in $HOME broke, including the entire i3blocks bar. All
repointed, and cpu_monitor/memory/disk/time/volume were run to confirm
they emit real output rather than merely resolving.
Verified: 1798 tests pass at 100% coverage, 8 of 9 lib/tests suites pass
(the ninth needs the coverage jail, identically at baseline), pre-commit
is clean, and the two untracked secret configs are still ignored after
their gitignore paths changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJrqKERAo5QUeEHWS5Asgp
197 lines
6.2 KiB
Bash
Executable File
197 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Fix/diagnose Xbox One (and 360) controllers on Arch Linux over USB.
|
|
# - Detects the device, relevant kernel modules, and evdev/joystick nodes
|
|
# - Loads safe modules (xpad, joydev) if missing
|
|
# - Shows dmesg hints and permission status
|
|
# - Suggests next steps (packages to test: evtest, joystick; drivers for BT/dongle)
|
|
#
|
|
# Conventions: sudo re-exec, idempotent, log with timestamps.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_NAME="$(basename "$0")"
|
|
LOG_FILE="/var/log/xbox-controller-fix.log"
|
|
|
|
timestamp() { date '+%Y-%m-%d %H:%M:%S%z'; }
|
|
|
|
log() {
|
|
local msg="$1"
|
|
echo "[$(timestamp)] $msg"
|
|
if [[ -w "$(dirname "$LOG_FILE")" ]] || [[ ! -e $LOG_FILE && -w /var/log ]]; then
|
|
echo "[$(timestamp)] $msg" >> "$LOG_FILE" || true
|
|
fi
|
|
}
|
|
|
|
require_root() {
|
|
if [[ ${EUID:-$(id -u)} -ne 0 ]]; then
|
|
echo "$SCRIPT_NAME needs root to load kernel modules and read some diagnostics. Re-executing with sudo..."
|
|
exec sudo -E bash "$0" "$@"
|
|
fi
|
|
}
|
|
|
|
print_header() {
|
|
echo "=== $1 ==="
|
|
}
|
|
|
|
detect_distro() {
|
|
if command -v pacman > /dev/null 2>&1; then
|
|
echo "arch"
|
|
else
|
|
echo "other"
|
|
fi
|
|
}
|
|
|
|
list_input_nodes() {
|
|
print_header "Input device nodes"
|
|
if [[ -d /dev/input/by-id ]]; then
|
|
# Robust listing with proper handling of special characters
|
|
local count=0
|
|
while IFS= read -r -d '' f; do
|
|
stat -c '%A %a %U:%G %N' "$f" 2> /dev/null || true
|
|
count=$((count + 1))
|
|
[[ $count -ge 120 ]] && break
|
|
done < <(find /dev/input/by-id -maxdepth 1 -mindepth 1 -print0 2> /dev/null)
|
|
else
|
|
echo "/dev/input/by-id not present"
|
|
fi
|
|
echo
|
|
if compgen -G "/dev/input/*js*" > /dev/null; then
|
|
ls -l /dev/input/js* || true
|
|
else
|
|
echo "No legacy /dev/input/js* nodes (joydev) present. That's okay for most apps using evdev."
|
|
fi
|
|
echo
|
|
}
|
|
|
|
show_lsusb() {
|
|
print_header "USB devices (filtered)"
|
|
if command -v lsusb > /dev/null 2>&1; then
|
|
lsusb | grep -Ei 'microsoft|xbox|045e:' || {
|
|
echo "No Microsoft/Xbox device found via lsusb."
|
|
true
|
|
}
|
|
else
|
|
echo "lsusb not found (usbutils). Install usbutils for richer diagnostics."
|
|
fi
|
|
echo
|
|
}
|
|
|
|
show_modules() {
|
|
print_header "Kernel modules state"
|
|
lsmod | grep -E '(^|\s)(xpad|joydev|hid_microsoft|hid_generic|hid_xpadneo|xone)(\s|$)' || echo "No matching modules currently loaded."
|
|
echo
|
|
}
|
|
|
|
modprobe_safe() {
|
|
local mod="$1"
|
|
if ! lsmod | grep -q "^${mod}\b"; then
|
|
if modprobe "$mod" 2> /dev/null; then
|
|
log "Loaded module: $mod"
|
|
else
|
|
log "Module $mod not loaded (may be built-in or unavailable)."
|
|
fi
|
|
fi
|
|
}
|
|
|
|
show_dmesg_hints() {
|
|
print_header "Recent kernel messages (xpad/xbox/hid/input)"
|
|
dmesg --color=never | grep -Ei 'xbox|xpad|045e:|Microsoft|input:.*gamepad|event.*joystick|hid.*(xbox|microsoft)' | tail -n 200 || true
|
|
echo
|
|
}
|
|
|
|
check_permissions() {
|
|
print_header "Permissions on event/joystick nodes"
|
|
local any=0
|
|
for path in /dev/input/by-id/*-event-joystick /dev/input/js*; do
|
|
if [[ -e $path ]]; then
|
|
any=1
|
|
printf '%s -> ' "$path"
|
|
local dev
|
|
dev=$(readlink -f "$path" 2> /dev/null || echo "$path")
|
|
stat -c '%A %a %U:%G %n' "$dev" 2> /dev/null || true
|
|
fi
|
|
done
|
|
if [[ $any -eq 0 ]]; then
|
|
echo "No event-joystick or js nodes found to check permissions."
|
|
fi
|
|
echo
|
|
if [[ $(detect_distro) == "arch" ]]; then
|
|
echo "On Arch, prefer TAG+\"uaccess\"-based access over adding users to the 'input' group."
|
|
echo "If access is denied in apps, install: pacman -S game-devices-udev (provides modern udev rules)."
|
|
fi
|
|
echo
|
|
}
|
|
|
|
suggest_tests() {
|
|
print_header "Next steps / tests"
|
|
echo "- Test evdev: install 'evtest' and run: evtest /dev/input/by-id/*-event-joystick"
|
|
echo "- Test joystick API: install 'joystick' (jstest) and run: jstest /dev/input/js0 (if present)"
|
|
echo "- For force feedback test (rumble): install 'linuxconsole' (fftest): fftest /dev/input/by-id/*-event-joystick"
|
|
echo
|
|
echo "Steam users: Ensure Steam Input settings match your use case. If rumble fails in SDL titles, try: SDL_JOYSTICK_HIDAPI=0"
|
|
echo
|
|
echo "If you are actually using Bluetooth: consider xpadneo (AUR: xpadneo-dkms)."
|
|
echo "If you are using the official wireless USB adapter: consider xone (AUR: xone-dkms and xone-dongle-firmware)."
|
|
echo
|
|
}
|
|
|
|
main() {
|
|
require_root "$@"
|
|
print_header "${SCRIPT_NAME} starting"
|
|
log "Kernel: $(uname -r) | Distro: $(detect_distro)"
|
|
|
|
show_lsusb
|
|
show_modules
|
|
|
|
# Load common modules safely (idempotent)
|
|
modprobe_safe usbhid
|
|
modprobe_safe xpad
|
|
modprobe_safe joydev
|
|
|
|
# If xpad failed to load and kernel says it's a module, but it's not present, hint about out-of-sync modules
|
|
if ! lsmod | grep -q '^xpad\b'; then
|
|
if command -v zcat > /dev/null 2>&1 && [[ -r /proc/config.gz ]] && zcat /proc/config.gz 2> /dev/null | grep -q '^CONFIG_JOYSTICK_XPAD=m'; then
|
|
if ! find "/lib/modules/$(uname -r)" -type f -name 'xpad*.ko*' 2> /dev/null | grep -q .; then
|
|
log "xpad is configured as a module but missing under /lib/modules/$(uname -r). Your kernel modules may be out-of-sync or incomplete."
|
|
if [[ $(detect_distro) == "arch" ]]; then
|
|
echo "Arch hint: reinstall the matching kernel package (e.g. 'sudo pacman -S linux' or your variant like linux-zen) and reboot."
|
|
else
|
|
echo "Hint: reinstall your running kernel's modules then reboot."
|
|
fi
|
|
echo
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
list_input_nodes
|
|
check_permissions
|
|
show_dmesg_hints
|
|
|
|
# Simple heuristic: do we see an Xbox/Microsoft event-joystick?
|
|
if compgen -G "/dev/input/by-id/*-event-joystick" > /dev/null; then
|
|
local found_label=0
|
|
for f in /dev/input/by-id/*-event-joystick; do
|
|
[[ -e $f ]] || continue
|
|
if printf '%s' "$(basename "$f")" | grep -Eqi 'xbox|microsoft|controller|wireless'; then
|
|
found_label=1
|
|
break
|
|
fi
|
|
done
|
|
if ((found_label == 1)); then
|
|
log "Controller event device detected."
|
|
else
|
|
log "Event-joystick device(s) exist but not obviously Xbox-labelled. Still likely usable."
|
|
fi
|
|
else
|
|
log "No -event-joystick device found. If the controller vibrated but no input node exists, check the cable and try another USB port/cable."
|
|
log "Also check dmesg for descriptor errors; for Xbox 360 Play&Charge cable: note it only charges and does not carry input."
|
|
fi
|
|
|
|
suggest_tests
|
|
|
|
print_header "Done"
|
|
}
|
|
|
|
main "$@"
|