Sub-frame latency
Each controller event is built into a 12-byte XUSB report, sealed, and sent via raw sendto() inline on the input thread. No queue, no async hop. Single-digit milliseconds end-to-end on a normal Wi-Fi 6 LAN.
Every input surface a modern controller has, forwarded over Wi-Fi with sub-frame latency.
Each controller event is built into a 12-byte XUSB report, sealed, and sent via raw sendto() inline on the input thread. No queue, no async hop. Single-digit milliseconds end-to-end on a normal Wi-Fi 6 LAN.
X25519 key exchange at pair time, ChaCha20-Poly1305 IETF on every packet, monotonic counter for replay defence. Same AEAD as TLS 1.3, WireGuard, and SSH. Auth tags are 128-bit, so forged inputs die in the receiver.
Satellite advertises _satellite._udp via Bonjour and answers a legacy UDP broadcast on :9879. Dish merges both and tags each entry with its source. Cold-cache discoveries usually finish in under a second.
Each side fires a heartbeat every 2 seconds. Five missed in a row reaps the connection. On a flap, Dish re-establishes against the saved key with no PIN re-entry. The virtual gamepad stays plugged in.
Each paired Dish picks its virtual identity. Satellite plugs an Xbox 360 pad via ViGEmBus or a DualShock 4 with full DS4 surface (motion, touchpad, lightbar, battery). Your call per controller.
MSG_MOTION (0x000A) streams 3-axis gyro and accelerometer at up to 250 Hz per controller in the Cemuhook DSU convention. Tilt-aim, gyro-look, or DSU-pipe to your favorite emulator on the receiver.
MSG_TOUCHPAD (0x000C) carries both DualSense fingers, monotonic tracking IDs, and the clicky-pad button. Pick per-device routing on the receiver: DS4 surface, host mouse, or off. Hot-swappable, no re-pair needed.
MSG_LIGHTBAR (0x000D) drives the DualSense and DS4 LEDs independently of rumble. Games that paint the bar to match in-world state (Astro's Playroom, GTA V, Returnal) work end-to-end across the LAN.
When a game writes to the virtual pad's rumble output, Satellite emits MSG_RUMBLE (0x0009) with strong + weak motor magnitudes back to the right Dish. On Android, by design, rumble lands on the phone's own vibrator(s) rather than the attached pad. Your hand feels it either way.
Controllers report level (0–100) and charge state every 30 seconds and on every transition. Wired or unknown pads fall back to the host device's battery, so you always see something meaningful in the slot card.
Dish for Android ships a configurable on-screen layout with Xbox and PlayStation profiles. D-pad, sticks, ABXY, triggers, all tweakable per-game. Eight-direction d-pad with diagonal sweet-spots, multi-finger L3/R3.
Dish for Android can also register itself as a Bluetooth HID gamepad. Pair it once to your PC, console, or TV box and forward inputs even when there's no Satellite on the network.
Satellite exposes a dashboard at localhost:9877. Live RTT per connection, paired devices, packet counters, loop microseconds, log tail, and a debug telemetry view. All over plain HTTP because the boundary is localhost.
Satellite tracks GitHub Releases on a stable or pre-release channel, downloads the platform artifact, verifies the SHA-256 against the cosign-signed sum file, and applies it via Inno Setup. Cancellable, skippable, dismissible.
Stream video with Moonlight, hold your Android phone as the controller via Dish. Or skip Moonlight entirely and use Dish as a wireless gamepad on the same monitor.
Satellite injects via ViGEmBus on Windows. Xbox 360 covers every PC game. DualShock 4 covers anything that prefers PlayStation buttons or wants the full touchpad / motion / lightbar surface.
Couch co-op night? Up to 16 controllers per Satellite session, with independent virtual pads, encryption state, motion streams, and rumble routes. A dropped player doesn't drag the others down.
Every outbound packet is marked Expedited Forwarding (DSCP EF / 0xB8). QoS-aware routers and APs jump them ahead of bulk traffic. Combined with thread-priority pinning on the receiver, this is what holds latency together on congested Wi-Fi.
Dish for Android ships English, Spanish, German, French, Brazilian Portuguese, and Bosnian out of the box. Strings are externalised so additional locales can land without a code change.
No analytics, no remote logging, no account system. The only outbound data path on Dish for Android is opt-out Firebase Crashlytics for crash and ANR reports: never gamepad input, never Satellite IPs, never SSIDs. Verifiable in the public repos.
Free, open source, and ten minutes from download to first frag.