> For the complete documentation index, see [llms.txt](https://docs.kouch.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kouch.dev/docs/adr/0004-rumble-paths.md).

# ADR 0004: Three rumble paths (A + B now, C opt-in)

## Status

Accepted (2026-09-17, owner decision after review — see `docs/ARCHITECTURE.md` "Decisions locked in with the user", row "Rumble").

## Context

DSU (ADR 0002) is the primary controller I/O path, but the base Cemuhook protocol has no official rumble/force-feedback message — only a widely implemented, unofficial extension that not every emulator supports. Some emulators already use DSU for everything including rumble; others (PCSX2-class) have no DSU input client at all and can only receive rumble through an XInput-style virtual gamepad; a third group (PPSSPP-class) is DSU-for-motion-only. A single rumble mechanism cannot cover all three cases, and Windows' only practical virtual-gamepad driver is an archived, unmaintained open-source project (see ADR 0002) — good enough to offer, never something Kouch can depend on being present.

## Decision

Kouch ships three rumble paths, added in this order and with different commitment levels:

* **(A) DSU rumble extension — required, Phase 1–2.** `kouch-dsu` implements the unofficial rumble extension (`0x110001` info / `0x110002` rumble request) and forwards requests to the platform input service's vibration call. This covers every emulator that already speaks DSU for buttons.
* **(B) Linux `uinput` virtual pads with force feedback — required, Phase 2 (Milestone 10).** `crates/kouch-vpad`'s `UinputPad` backend exposes force-feedback-capable virtual devices with no driver requirement on Linux/Deck, covering emulators with no DSU rumble support at all on that platform.
* **(C) Windows opt-in virtual pad backend — optional, Phase 2 (Milestone 11).** A `vigem-client`-based backend is offered **per-profile, opt-in only**, with a one-click installer URL Kouch never runs automatically, behind the same `VirtualPad` trait as (B) so the underlying driver stays swappable. Kouch's core function never depends on it being installed.

## Consequences

* Rumble coverage is emulator- and platform-dependent by design, and this must be documented per profile (`docs/ARCHITECTURE.md`'s profile validation warns when a profile's players carry buttons on both a DSU slot and a vpad, to catch accidental double-input as well as to surface which rumble path is actually active).
* Path (C) being opt-in and driver-absent-tolerant means "Kouch still runs with the driver absent" is a testable acceptance criterion (Milestone B9 / Execution-order Milestone 11), not just a hope — the code path must degrade gracefully, not fail to start.
* If path (C)'s underlying driver ever stops working on a future Windows release, the fallback (per the backend risks table in `docs/ARCHITECTURE.md`) is to drop Windows rumble down to DSU-only (path A) and re-evaluate alternatives (a DirectInput joystick driver, or a platform-native virtual device API), rather than blocking a Windows release on a third-party driver's maintenance status.
* `rumble-roundtrip` (Early Test 16) is the acceptance gate for all three paths together and must be re-run whenever any of the three implementations changes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.kouch.dev/docs/adr/0004-rumble-paths.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
