Skip to content

Commit c75d5d7

Browse files
feat(input): update libvirtualhid integration (#5563)
1 parent 377e07c commit c75d5d7

32 files changed

Lines changed: 347 additions & 93 deletions

.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: 18 additions & 8 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
@@ -476,10 +480,10 @@ and enter its device name in the [audio_sink](configuration.md#audio_sink) field
476480
### Windows
477481
Sunshine uses libvirtualhid for virtual input on Windows. You must install the
478482
[Virtual HID Driver](https://github.com/LizardByte/libvirtualhid/releases/latest) separately for a driver-backed Raw
479-
Input mouse and full virtual gamepad support. ViGEmBus is detected only as a limited fallback for Xbox 360 and
480-
DualShock 4 gamepads when libvirtualhid is unavailable.
483+
Input keyboard and mouse plus full virtual gamepad support. ViGEmBus is detected only as a limited fallback for Xbox
484+
360 and DualShock 4 gamepads when libvirtualhid is unavailable.
481485

482-
Sunshine requires Virtual HID Driver version `2026.823.352.3` or newer. Earlier releases use incompatible Windows
486+
Sunshine requires Virtual HID Driver version `2026.829.2338.54` or newer. Earlier releases use incompatible Windows
483487
control and broker protocols and must be upgraded together with Sunshine's embedded libvirtualhid library. Local
484488
development driver builds using a `0.0.0.*` version remain supported.
485489

@@ -488,15 +492,21 @@ Pro, and Generic gamepads in addition to Xbox 360 and DualShock 4. It can also e
488492
as motion, touchpads, LEDs, and adaptive triggers when supported. Virtual HID Driver is actively developed and
489493
supported by the LizardByte team.
490494

491-
With a compatible driver and active license, relative mouse movement, buttons, and scrolling are exposed as a real HID
495+
With a compatible driver and active license, normal key transitions are exposed through a real HID keyboard so
496+
applications using Raw Input can receive them. Unicode text input and keys outside the supported HID keyboard page
497+
continue to use Windows input injection. When the driver-backed keyboard cannot be created because the driver,
498+
broker, or license is unavailable, libvirtualhid retains its legacy SendInput fallback.
499+
500+
Relative mouse movement, buttons, and scrolling are exposed as a real HID
492501
mouse so applications using Raw Input can receive them. Absolute mouse positioning continues to use Windows input
493502
injection. When the driver-backed mouse cannot be created, libvirtualhid retains its legacy SendInput fallback.
494503

495504
The Virtual HID Driver requires an active machine license for driver-backed devices, including gamepads and the Raw
496-
Input mouse. Sunshine shows the current license status and actions on the Web UI Troubleshooting page and in the
497-
**Virtual HID Driver** system tray submenu. When Sunshine starts on an unactivated machine, select its tray notification
498-
to open the activation and purchase options in the Web UI. Sunshine recreates the shared mouse after a successful
499-
license action, so switching between the HID and SendInput paths does not require restarting Sunshine.
505+
Input keyboard and mouse. Sunshine shows the current license status and actions on the Web UI Troubleshooting page and
506+
in the **Virtual HID Driver** system tray submenu. When Sunshine starts on an unactivated machine, select its tray
507+
notification to open the activation and purchase options in the Web UI. Sunshine recreates the shared keyboard and
508+
mouse after a successful license action, so switching between the HID and SendInput paths does not require restarting
509+
Sunshine.
500510

501511
After installing or updating virtual input drivers, it is recommended to restart your computer.
502512

docs/troubleshooting.md

Lines changed: 30 additions & 8 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
@@ -292,11 +304,11 @@ launchctl load -w /Library/LaunchAgents/org.freedesktop.dbus-session.plist
292304
### No gamepad detected
293305
Sunshine uses libvirtualhid for virtual input on Windows. Install the
294306
[Virtual HID Driver](https://github.com/LizardByte/libvirtualhid/releases/latest) separately for a driver-backed Raw
295-
Input mouse and full virtual gamepad support. ViGEmBus is detected only as a limited fallback for Xbox 360 and
296-
DualShock 4 gamepads when libvirtualhid is unavailable. If you use the
307+
Input keyboard and mouse plus full virtual gamepad support. ViGEmBus is detected only as a limited fallback for Xbox
308+
360 and DualShock 4 gamepads when libvirtualhid is unavailable. If you use the
297309
[ViGEmBus fallback](https://github.com/nefarius/ViGEmBus/releases/latest), you must use version 1.17 or newer.
298310
299-
Sunshine requires Virtual HID Driver version `2026.823.352.3` or newer. Earlier releases use incompatible Windows
311+
Sunshine requires Virtual HID Driver version `2026.829.2338.54` or newer. Earlier releases use incompatible Windows
300312
control and broker protocols. The Troubleshooting page reports an older installed package as unsupported and links
301313
to the current driver release. Local development driver builds using a `0.0.0.*` version remain supported.
302314
@@ -305,21 +317,31 @@ controller features such as motion, touchpads, LEDs, and adaptive triggers when
305317
ViGEmBus project, Virtual HID Driver is actively developed and supported by the LizardByte team.
306318
307319
An active Virtual HID Driver machine license is required before Sunshine can create driver-backed libvirtualhid
308-
devices, including gamepads and the Raw Input mouse. Follow the warning on the Web UI home page, the startup tray
309-
notification, or the **Virtual HID Driver** tray submenu to open the license section on the Troubleshooting page, where
310-
you can activate a key or follow the purchase link.
320+
devices, including gamepads and the Raw Input keyboard and mouse. Follow the warning on the Web UI home page, the
321+
startup tray notification, or the **Virtual HID Driver** tray submenu to open the license section on the
322+
Troubleshooting page, where you can activate a key or follow the purchase link.
311323
312324
After installation, it is recommended to restart your computer.
313325
326+
### Games do not detect keyboard input
327+
With a compatible Virtual HID Driver and active license, Sunshine sends normal key transitions through a real HID
328+
keyboard so games using Raw Input can receive them. Unicode text input and keys outside the supported HID keyboard
329+
page continue to use Windows input injection. When the driver-backed keyboard cannot be created because the driver,
330+
broker, or license is unavailable, libvirtualhid falls back to SendInput.
331+
332+
Check the Virtual HID Driver version and license sections on the Web UI Troubleshooting page. Sunshine recreates the
333+
shared keyboard and mouse after a successful license activation, validation, or deactivation, so you do not need to
334+
restart Sunshine merely to switch between the HID and SendInput paths.
335+
314336
### Games do not detect mouse input
315337
With a compatible Virtual HID Driver and active license, Sunshine sends relative mouse movement, buttons, and scrolling
316338
through a real HID device so games using Raw Input can receive them. Absolute positioning still uses Windows input
317339
injection. When the driver-backed mouse cannot be created, libvirtualhid falls back to SendInput; the Windows cursor may
318340
still move even though a game that listens only for Raw Input receives nothing.
319341
320342
Check the Virtual HID Driver version and license sections on the Web UI Troubleshooting page even when controller input
321-
is disabled. Sunshine recreates the shared mouse after a successful license activation, validation, or deactivation, so
322-
you do not need to restart Sunshine merely to switch between the HID and SendInput paths.
343+
is disabled. The same live refresh used by the keyboard path also switches the mouse between HID and SendInput without
344+
requiring a Sunshine restart.
323345
324346
### Permission denied
325347
Since Sunshine runs as a service on Windows, it may not have the same level of access that your regular user account

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)