#!/bin/bash # Quick diagnostic: is uinput functional on this kernel? # Sunshine uses libevdev/uinput for keyboard/mouse injection, NOT XTEST. # If this script fails, all input will be silently broken regardless of # Moonlight settings, admin rights, or WM choice. set -e echo "=== uinput diagnostic for Sunshine game streaming ===" echo "Kernel: $(uname -r)" echo "" # Check 1: basic device node if [ -e /dev/uinput ]; then echo "[PASS] /dev/uinput exists" else echo "[FAIL] /dev/uinput does not exist" exit 1 fi # Check 2: writable if [ -w /dev/uinput ]; then echo "[PASS] /dev/uinput is writable" else echo "[FAIL] /dev/uinput is NOT writable" echo " Fix: sudo usermod -a -G input $USER && newgrp input" exit 1 fi # Check 3: libevdev uinput create (the exact API Sunshine uses) python3 -c ' import ctypes, sys libevdev = ctypes.CDLL("libevdev.so.2") dev = libevdev.libevdev_new() if not dev: print("[FAIL] libevdev_new() returned NULL") sys.exit(1) libevdev.libevdev_set_name(dev, b"diagnose-uinput") libevdev.libevdev_enable_event_type(dev, 1) # EV_KEY uinput_fd = ctypes.c_int(-1) ret = libevdev.libevdev_uinput_create_from_device(dev, 3, ctypes.byref(uinput_fd)) libevdev.libevdev_free(dev) if ret == 0 and uinput_fd.value >= 0: print(f"[PASS] uinput device created (fd={uinput_fd.value})") import os; os.close(uinput_fd.value) elif ret < 0: import errno errname = errno.errorcode.get(-ret, f"unknown({ret})") print(f"[FAIL] uinput create returned {ret} (errno: {errname})") if ret == -25: print(" ENOTTY: uinput interface broken on this kernel (known on 7.0.0-22)") print(" Workaround: Steam Remote Play or boot older kernel") sys.exit(1) else: print(f"[FAIL] uinput create returned {ret}") sys.exit(1) ' echo "" echo "=== Diagnostic complete ==="