63 lines
1.9 KiB
C
63 lines
1.9 KiB
C
/*
|
|
* LD_PRELOAD shim for Sunshine on kernel 7.0+.
|
|
*
|
|
* PROBLEM: Kernel 7.0 (confirmed: 7.0.0-22-generic) requires UI_DEV_SETUP ioctl
|
|
* BEFORE UI_DEV_CREATE on /dev/uinput. The old write()+UI_DEV_CREATE sequence
|
|
* and bare UI_DEV_CREATE both fail with EINVAL. Sunshine links against
|
|
* libevdev which uses the old method. Result: keyboard and mouse input silently
|
|
* fail (Sunshine receives Moonlight packets but can't inject into X11).
|
|
*
|
|
* FIX: This shim overrides libevdev_uinput_create_from_device() to use the
|
|
* correct UI_DEV_SETUP + UI_DEV_CREATE sequence.
|
|
*
|
|
* COMPILE: gcc -shared -fPIC -o uinput_fix.so uinput-shim.c -ldl
|
|
*
|
|
* DEPLOY:
|
|
* 1. cp uinput_fix.so ~/.config/sunshine/uinput_fix.so
|
|
* 2. Add to Sunshine systemd override:
|
|
* [Service]
|
|
* Environment=LD_PRELOAD=/home/ray/.config/sunshine/uinput_fix.so
|
|
* 3. systemctl --user daemon-reload
|
|
* 4. systemctl --user restart sunshine
|
|
*
|
|
* VERIFY: After connecting Moonlight, check that input events are created:
|
|
* grep "keyboard packet" ~/.config/sunshine/sunshine.log | tail -5
|
|
* # Should see packets arriving, AND keyboard/mouse now works on client.
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/uinput.h>
|
|
|
|
int libevdev_uinput_create_from_device(void *dev, int flags, int *uifd) {
|
|
int fd = open("/dev/uinput", O_WRONLY);
|
|
if (fd < 0) { return -errno; }
|
|
|
|
struct uinput_setup usetup;
|
|
memset(&usetup, 0, sizeof(usetup));
|
|
usetup.id.bustype = BUS_USB;
|
|
usetup.id.vendor = 0x1234;
|
|
usetup.id.product = 0x5678;
|
|
strncpy(usetup.name, "Sunshine Keyboard", UINPUT_MAX_NAME_SIZE-1);
|
|
|
|
if (ioctl(fd, UI_DEV_SETUP, &usetup) < 0) {
|
|
close(fd);
|
|
return -errno;
|
|
}
|
|
|
|
if (ioctl(fd, UI_DEV_CREATE) < 0) {
|
|
close(fd);
|
|
return -errno;
|
|
}
|
|
|
|
*uifd = fd;
|
|
return 0;
|
|
}
|