diff --git a/docs/USAGE.md b/docs/USAGE.md index a881231..bdd8b48 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -1,58 +1,212 @@ -# Host +# Usage Guide -Assumption vuinputd is running. +This guide explains how to run applications that use `/dev/uinput` (like [Sunshine](https://github.com/LizardByte/Sunshine)) inside containers using **`vuinputd`**. +You’ll learn how to connect your container to the host’s input proxy, configure permissions, and verify that input devices are visible and functional inside the container. -## docker -``` -sudo bash -apt-get install docker.io -# first time -docker run -it --name vuinput-test --device=/dev/vuinput:/dev/uinput --device-cgroup-rule='c 13:* rw' --mount type=bind,src=(insert build directory here),dst=/build ubuntu:noble -# subsequent times -# docker start -ia vuinput-test -``` -Now continue with the instructions given below in section Inside Container. Afterwards, you can remove the container with `docker rm vuinput-test`. +--- -## systemd-nspawn +## 1. Overview -TODO: more details +`vuinputd` allows unmodified apps that use `/dev/uinput` to run safely inside containers. +It provides each container with a **virtual `/dev/uinput`**, while a **host-side daemon** mediates all access to the real uinput subsystem. -Install mkosi from https://github.com/systemd/mkosi. Manual is on https://github.com/systemd/mkosi/blob/main/mkosi/resources/man/mkosi.1.md +This guide shows how to: -Create a Ubuntu 24.04 with `mkosi -d ubuntu -r noble -t directory ubuntu-dir +1. Run a container (Docker, systemd-nspawn, or LXC/LXD) +2. Connect it to the host’s virtual `/dev/uinput` +3. Verify that device creation and input forwarding work correctly -``` -/usr/bin/systemd-nspawn -M gamestreamingserver -D ubuntu-dir --network-veth --system-call-filter="@keyring bpf" --bind=/proc:/run/proc --bind=/sys:/run/sys --bind=/dev/vuinput:/dev/uinput --bind=/dev/dri --property="DeviceAllow=char-drm rw" -b --property="DeviceAllow=char-input rw" --property="DeviceAllow=/dev/vuinput rw" -``` +--- -## lxd/lxc +## 2. Prerequisites -TODO: more details -``` -lxc.cgroup2.devices.allow: c 120:414795 rwm -lxc.mount.entry: /dev/vuinput dev/uinput none bind,optional,create=file +Before continuing, ensure the following: -``` +* `vuinputd` is **installed and running** on the host + → see [docs/BUILD.md](BUILD.md) +* You have **root access** on the host (required for mounting and device permissions) +* The host kernel supports: -# Inside Container -``` + * `/dev/uinput` + * FUSE/`CUSE` +* Optional tools for debugging and validation inside the container: + + ```bash + apt-get install libinput-tools evtest udev tmux + ``` + +--- + +## 3. Quick Start (Docker Example) + +This is the simplest way to verify that `vuinputd` works. + +### 🖥️ On the Host + +1. Install Docker: + + ```bash + sudo apt-get install docker.io + ``` + +2. Start a test container with `vuinputd`’s virtual device mapped in: + + ```bash + sudo docker run -it \ + --name vuinput-test \ + --device=/dev/vuinput:/dev/uinput \ + --device-cgroup-rule='c 13:* rw' \ + --mount type=bind,src=,dst=/build \ + ubuntu:noble + ``` + + *(Replace `` with your actual build directory)* + +3. Test the application + +Just run those lines in the container. +```bash +# Allow access for any application chmod 666 /dev/uinput -apt-get update -# install test tools (not necessary for production) -apt-get install libinput-tools udev evtest tmux -# create dummy files (necessary for production) +# Prepare udev stubs so applications relying on libudev work mkdir -p /run/udev/data/ touch /run/udev/control - -# now for the test open a tmux session with four windows -# see https://tmuxcheatsheet.com/ -# to create a window, press Ctrl+b, then c -# to switch to the next window, press Ctrl+b, then n (next) -libinput debug-events -udevadm monitor -p -evtest /dev/input/event* +# Run the demo application /build/release/mouse-advanced ``` +The `vuinputd` daemon on the host should provide some logs. The following section "Verifying Operation" describes a more elaborate check and also some screenshots. + +4. Optional: To reuse the container later: + + ```bash + sudo docker start -ia vuinput-test + ``` + +5. To clean up: + + ```bash + sudo docker rm vuinput-test + ``` + +--- + +## 4. Runtime-Specific Setup + +### 🐳 Docker + +(As shown above in Quick Start.) + +**Key flags:** + +* `--device=/dev/vuinput:/dev/uinput` — mounts the fake uinput device +* `--device-cgroup-rule='c 13:* rw'` — allows access to input devices +* Optional: bind your build directory to `/build` for testing binaries + +--- + +### 🧱 systemd-nspawn + +1. Install [mkosi](https://github.com/systemd/mkosi): + + ```bash + sudo apt-get install mkosi + ``` + +2. Create an Ubuntu 24.04 image: + + ```bash + mkosi -d ubuntu -r noble -t directory ubuntu-dir + ``` + +3. Launch a container with `vuinputd` bound: + + ```bash + /usr/bin/systemd-nspawn \ + -M vuinputtest \ + -D ubuntu-dir \ + --network-veth \ + --system-call-filter="@keyring bpf" \ + --bind=/proc:/run/proc \ + --bind=/sys:/run/sys \ + --bind=/dev/vuinput:/dev/uinput \ + --bind=/dev/dri \ + --property="DeviceAllow=char-drm rw" \ + --property="DeviceAllow=char-input rw" \ + --property="DeviceAllow=/dev/vuinput rw" \ + -b + ``` + +--- + +### 🪶 LXC / LXD + +Add the following to your container configuration: + +```ini +lxc.cgroup2.devices.allow: c 120:414795 rwm +lxc.mount.entry: /dev/vuinput dev/uinput none bind,optional,create=file +``` + +Then restart the container. + +*(Adjust the major/minor numbers to match `/dev/vuinput` on your host — check with `ls -l /dev/vuinput`. In the current release, 120:414795 is hardcoded. This may change in the future.)* + +--- + +## 5. Inside the Container + +Once inside the container shell: + +```bash +chmod 666 /dev/uinput +apt-get update + +# Optional: install test tools +apt-get install libinput-tools udev evtest tmux + +# Prepare udev stubs +mkdir -p /run/udev/data/ +touch /run/udev/control +``` + +--- + +## 6. Verifying Operation + +To test everything, use multiple `tmux` windows for parallel monitoring. + +1. Start `libinput` event monitor: + + ```bash + libinput debug-events + ``` + +2. In another window, observe udev events: + + ```bash + udevadm monitor -p + ``` + +3. In a third, run: + + ```bash + evtest /dev/input/event* + ``` + +4. Finally, run the demo binary: + + ```bash + /build/release/mouse-advanced + ``` + +### Expected Results + +You should see: + +* `libinput` reporting device creation and input events +* `udevadm` announcing a new `/dev/input/event*` +* `evtest` showing input data (e.g. mouse movement) +* `journalctl` on the host showing `vuinputd` logs about device creation and event forwarding Sample output from `libinput debug-events`: @@ -67,4 +221,36 @@ Sample output from `evtest`: Sample output from `journalctl` showing vuinputd output: - \ No newline at end of file + + +--- + +## 7. Troubleshooting + +| Symptom | Possible Cause | Fix | +| --------------------------- | ------------------------------------ | ------------------------------------------------- | +| `/dev/uinput` not found | `vuinputd` not running | Start `vuinputd` on host | +| Permission denied | Missing `chmod` or wrong cgroup rule | Run `chmod 666 /dev/uinput` or adjust device rule | +| No events in container | Missing `/run/udev/control` | Create dummy udev files (see section 5) | +| Device appears on host seat | udev rules not isolating | Add udev rules from vuinputd/udev-folder | +| Input delayed or missing | CUSE layer error | Check host logs via `journalctl -u vuinputd` | + +--- + +## 8. Notes and Advanced Topics + +* You can safely run **multiple containers**. +* Devices are automatically cleaned up when the container stops. +* Works with **Wayland** and **X11** compositors using libinput. +* For deeper details, see: + + * [docs/DESIGN.md](DESIGN.md) + * [docs/BUILD.md](BUILD.md) + +--- + +## 9. References + +* [mkosi manual](https://github.com/systemd/mkosi/blob/main/mkosi/resources/man/mkosi.1.md) +* [Docker device rules documentation](https://docs.docker.com/engine/reference/run/#device-cgroup-rule) +* [libinput tools](https://wayland.freedesktop.org/libinput/doc/latest/tools.html) \ No newline at end of file