Skip to content

Commit 50c5419

Browse files
Fix udev rules for virtual gamepad nodes
Extend udev rule reloading to cover hidraw and input subsystems so permissions are applied to dynamically created libvirtualhid gamepad child nodes, not just /dev/uinput and /dev/uhid. Also: - Always install the udev rules file regardless of whether libudev is detected at build time - Add Homebrew postinst support to copy rules to host-monitored directories - Trigger udevadm reload on rule removal (AppImage, Flatpak) - Update comments to say "gamepad emulation" instead of "DS5 emulation" - Add docs clarifying that manual chmod/setfacl changes are lost on reconnect and how to reload rules
1 parent 2ab80c8 commit 50c5419

16 files changed

Lines changed: 104 additions & 21 deletions

File tree

.github/workflows/ci-archlinux.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ jobs:
149149
_support_headless_testing="${_support_headless_testing}" \
150150
makepkg -si --noconfirm
151151
152+
# Native packages must install the host rule used by dynamically
153+
# created libvirtualhid hidraw and input event nodes.
154+
test -f /usr/lib/udev/rules.d/60-sunshine.rules
155+
grep -Fq 'IMPORT{parent}="HID_*"' \
156+
/usr/lib/udev/rules.d/60-sunshine.rules
157+
grep -Fq 'ENV{HID_PHYS}=="libvirtualhid/uhid/*"' \
158+
/usr/lib/udev/rules.d/60-sunshine.rules
159+
udevadm verify /usr/lib/udev/rules.d/60-sunshine.rules
160+
152161
# Remove debug package
153162
rm -f sunshine-debug*.pkg.tar.zst
154163

.github/workflows/ci-linux.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ jobs:
103103
run: |
104104
# install sunshine to the DESTDIR
105105
DESTDIR=AppDir ninja install
106+
test -f AppDir/usr/share/sunshine/udev/rules.d/60-sunshine.rules
107+
grep -Fq 'IMPORT{parent}="HID_*"' \
108+
AppDir/usr/share/sunshine/udev/rules.d/60-sunshine.rules
109+
grep -Fq 'ENV{HID_PHYS}=="libvirtualhid/uhid/*"' \
110+
AppDir/usr/share/sunshine/udev/rules.d/60-sunshine.rules
106111
107112
# custom AppRun file
108113
cp -f ../packaging/linux/AppImage/AppRun ./AppDir/

.github/workflows/ci-macos.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,11 @@ jobs:
5858
- os: "macos-14"
5959
name: "macOS-arm64"
6060
arch: "arm64"
61+
build_docs: "ON"
6162
- os: "macos-15-intel"
6263
name: "macOS-x86_64"
6364
arch: "x86_64"
65+
build_docs: "OFF"
6466
steps:
6567
- name: Install Apple certificate
6668
uses: apple-actions/import-codesign-certs@5142e029c445c10ffc7149d172e540235a065466 # v7.0.0
@@ -121,6 +123,7 @@ jobs:
121123
cmake \
122124
-B build \
123125
-S . \
126+
-DBUILD_DOCS="${{ matrix.build_docs }}" \
124127
-DBUILD_WERROR=ON \
125128
-DCMAKE_BUILD_TYPE=Release \
126129
-DICU_ROOT="$(brew --prefix icu4c@78 2>/dev/null)" \

cmake/packaging/linux.cmake

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@ else()
3030
find_package(Udev)
3131

3232
if(UDEV_FOUND)
33-
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.rules"
34-
DESTINATION "${UDEV_RULES_INSTALL_DIR}")
33+
set(SUNSHINE_UDEV_RULES_INSTALL_DIR "${UDEV_RULES_INSTALL_DIR}")
34+
else()
35+
set(SUNSHINE_UDEV_RULES_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/udev/rules.d")
36+
message(WARNING
37+
"Could not determine the host udev rules directory; "
38+
"installing Sunshine rules to ${SUNSHINE_UDEV_RULES_INSTALL_DIR}")
3539
endif()
40+
install(FILES "${SUNSHINE_SOURCE_ASSETS_DIR}/linux/misc/60-sunshine.rules"
41+
DESTINATION "${SUNSHINE_UDEV_RULES_INSTALL_DIR}")
3642
if(SYSTEMD_FOUND)
3743
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/app-${PROJECT_FQDN}.service"
3844
DESTINATION "${SYSTEMD_USER_UNIT_INSTALL_DIR}")

docs/getting_started.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ flatpak install --user ./sunshine_{arch}.flatpak
265265
```
266266

267267
##### Additional installation (required)
268+
Run this command after installing or updating the Flatpak so the privileged host
269+
udev rules stay synchronized with Sunshine:
270+
268271
```bash
269272
flatpak run --command=additional-install.sh dev.lizardbyte.app.Sunshine
270273
```
@@ -293,6 +296,7 @@ brew update
293296
brew upgrade
294297
brew tap LizardByte/homebrew
295298
brew install sunshine
299+
sudo "$(brew --prefix sunshine)/bin/postinst"
296300
```
297301

298302
##### Uninstall

docs/troubleshooting.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,18 @@ flatpak permission-set kde-authorized remote-desktop dev.lizardbyte.app.Sunshine
188188
After installation, the `udev` rules need to be reloaded. Our post-install script tries to do this for you
189189
automatically, but if it fails, you may need to restart your system.
190190
191+
Sunshine recreates virtual gamepad device nodes for each streaming session. Manual `chmod` or `setfacl`
192+
changes therefore disappear when the client reconnects. Confirm that the installed Sunshine rule contains the
193+
parent-property import and `libvirtualhid/uhid/*` match, then reload it and reapply it to existing gamepad nodes:
194+
195+
```bash
196+
grep -R -E 'IMPORT\{parent\}="HID_\*"|ENV\{HID_PHYS\}=="libvirtualhid/uhid/\*"' \
197+
/etc/udev/rules.d /usr/lib/udev/rules.d /lib/udev/rules.d 2>/dev/null
198+
sudo udevadm control --reload-rules
199+
sudo udevadm trigger --subsystem-match=hidraw
200+
sudo udevadm trigger --subsystem-match=input
201+
```
202+
191203
If the input is still not working, you may need to add your user to the `input` group.
192204
193205
```bash

packaging/linux/AppImage/AppRun

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ echo "
2828
------ # This message
2929
3030
$ARGV0 --install, -i
31-
# Install input rules sunshine.service files. Restart required.
31+
# Install or update input rules and sunshine.service files.
3232
3333
$ARGV0 --remove, -r
3434
# Remove input rules sunshine.service files.
@@ -52,6 +52,8 @@ function install() {
5252
sudo udevadm control --reload-rules
5353
sudo udevadm trigger --property-match=DEVNAME=/dev/uinput
5454
sudo udevadm trigger --property-match=DEVNAME=/dev/uhid
55+
sudo udevadm trigger --subsystem-match=hidraw
56+
sudo udevadm trigger --subsystem-match=input
5557

5658
# sunshine service
5759
mkdir -p ~/.config/systemd/user
@@ -66,6 +68,7 @@ function install() {
6668
function remove() {
6769
# remove input rules
6870
sudo rm -f /etc/udev/rules.d/60-sunshine.rules
71+
sudo udevadm control --reload-rules
6972

7073
# remove uhid module loading config
7174
sudo rm -f /etc/modules-load.d/60-sunshine.conf

packaging/linux/Arch/sunshine.install

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
# shellcheck shell=bash
2+
13
do_setcap() {
2-
setcap cap_sys_admin,cap_sys_nice+p $(readlink -f usr/bin/sunshine)
4+
setcap cap_sys_admin,cap_sys_nice+p "$(readlink -f usr/bin/sunshine)"
35
}
46

57
do_udev_reload() {
68
udevadm control --reload-rules
79
udevadm trigger --property-match=DEVNAME=/dev/uinput
810
udevadm trigger --property-match=DEVNAME=/dev/uhid
11+
udevadm trigger --subsystem-match=hidraw
12+
udevadm trigger --subsystem-match=input
913
modprobe uinput || true
1014
modprobe uhid || true
1115
}

packaging/linux/copr/Sunshine.spec

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -414,21 +414,23 @@ cd %{_builddir}/Sunshine/build
414414
%post
415415
# Note: this is copied from the postinst script
416416

417-
# Load uhid (DS5 emulation)
418-
echo "Loading uhid kernel module for DS5 emulation."
417+
# Load uhid for descriptor-driven gamepad emulation
418+
echo "Loading uhid kernel module for gamepad emulation."
419419
modprobe uhid
420420

421421
# Check if we're in an rpm-ostree environment
422422
if [ ! -x "$(command -v rpm-ostree)" ]; then
423423
echo "Not in an rpm-ostree environment, proceeding with post install steps."
424424

425-
# Trigger udev rule reload for /dev/uinput and /dev/uhid
425+
# Reload the rules and reapply them to virtual gamepad child nodes.
426426
path_to_udevadm=$(which udevadm)
427427
if [ -x "$path_to_udevadm" ]; then
428428
echo "Reloading udev rules."
429429
$path_to_udevadm control --reload-rules
430430
$path_to_udevadm trigger --property-match=DEVNAME=/dev/uinput
431431
$path_to_udevadm trigger --property-match=DEVNAME=/dev/uhid
432+
$path_to_udevadm trigger --subsystem-match=hidraw
433+
$path_to_udevadm trigger --subsystem-match=input
432434
echo "Udev rules reloaded successfully."
433435
else
434436
echo "error: udevadm not found or not executable."

packaging/linux/flatpak/scripts/additional-install.sh

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ cp "/app/share/sunshine/systemd/user/app-dev.lizardbyte.app.Sunshine.service" "$
66
echo "Sunshine User Service has been installed."
77
echo "Use [systemctl --user enable app-dev.lizardbyte.app.Sunshine] once to autostart Sunshine on login."
88

9-
# Load uhid (DS5 emulation)
9+
# Load uhid for descriptor-driven gamepad emulation
1010
UHID=$(cat /app/share/sunshine/modules-load.d/60-sunshine.conf)
11-
echo "Enabling DS5 emulation."
11+
echo "Enabling gamepad emulation."
1212
flatpak-spawn --host pkexec sh -c "echo '$UHID' > /etc/modules-load.d/60-sunshine.conf"
1313
flatpak-spawn --host pkexec modprobe uhid
1414

1515
# Udev rule
1616
UDEV=$(cat /app/share/sunshine/udev/rules.d/60-sunshine.rules)
17-
echo "Configuring mouse permission."
17+
echo "Configuring virtual input permissions."
1818
flatpak-spawn --host pkexec sh -c "echo '$UDEV' > /etc/udev/rules.d/60-sunshine.rules"
19-
echo "Restart computer for mouse permission to take effect."
19+
flatpak-spawn --host pkexec udevadm control --reload-rules
20+
flatpak-spawn --host pkexec udevadm trigger --property-match=DEVNAME=/dev/uinput
21+
flatpak-spawn --host pkexec udevadm trigger --property-match=DEVNAME=/dev/uhid
22+
flatpak-spawn --host pkexec udevadm trigger --subsystem-match=hidraw
23+
flatpak-spawn --host pkexec udevadm trigger --subsystem-match=input
24+
echo "Virtual input permissions have been updated."

0 commit comments

Comments
 (0)