How it works

From a button press to a virtual gamepad.

You don't have to read any of this to use Dish. It just works. But if you want to know what your input is doing between your thumb and the game, this is the whole trip: input, encryption, transport, injection, and the return path.

  1. 1

    You press a button on Dish

    Maybe it's a tap on Dish for Android's touch overlay. Maybe it's a DualSense L1 Bluetooth-paired to your phone and bridged through Dish. Either way Dish grabs the input event from the OS the moment it fires. Not at the next vsync, not on the next frame. Now.

  2. 2

    Dish builds a 12-byte XUSB report

    The controller state goes into Satellite's compact wire format: two bytes of buttons, one byte per trigger, two bytes per analog stick axis. Twelve bytes total. Binary-compatible with Windows' XINPUT report, so the receiver doesn't have to translate anything.

  3. 3

    It encrypts the packet

    Dish prepends a 4-byte session token and a 4-byte counter, then seals the payload with ChaCha20-Poly1305 IETF using the 32-byte symmetric key both ends derived from the X25519 key exchange at pair time. The counter doubles as nonce and as replay defence; the token is authenticated as AAD so it can't be tampered with.

  4. 4

    It's sent over UDP

    Dish opens one UDP socket on port 9876 and calls sendto straight from the input thread. No queue, no async runtime, no ring buffer. The packet is tagged DSCP EF (Expedited Forwarding, 0xB8), so any QoS-aware router or AP on your LAN jumps it ahead of bulk traffic.

  5. 5

    Satellite receives and verifies

    On your Windows gaming PC, Satellite is parked on its UDP socket on a time-critical thread waiting. The instant a packet lands it's MAC-verified, decrypted, and checked against the highest counter we've already accepted on this connection. Anything stale, forged, or tampered is dropped silently, so your game never sees a corrupt input.

  6. 6

    Satellite injects a virtual pad

    Satellite hands the report to the ViGEmBus kernel driver in a single DeviceIoControl call. You choose per controller whether to plug in an Xbox 360 pad or a DualShock 4. DS4 gets the full surface: motion, touchpad fingers, lightbar, and battery, all reported back to the game.

  7. 7

    The game responds, and answers back

    The game reads the new pad state on its next input poll, usually inside one frame at 60 fps. When the game writes rumble back, or paints the lightbar a new color, Satellite encrypts and ships MSG_RUMBLE or MSG_LIGHTBAR back to the right Dish, which actuates haptics and LED in your hand. Total finger-to-pixel latency: a handful of milliseconds plus whatever your monitor's frame time adds.

Pairing happens once

The first time a Dish meets a new Satellite, you tap "Generate PIN" in Satellite's tray menu or web UI. Satellite shows a 4-digit code that lives for 5 minutes. Dish posts its X25519 public key plus that PIN to https://<your-pc>:9443/api/pair. Satellite verifies the PIN, computes the shared secret, returns its public key, and both sides cache the resulting 32-byte symmetric key. From then on the pad reconnects silently. No PIN, no UI, no thinking.

"But what about Sunshine and Moonlight?"

Sunshine and Moonlight are still the gold standard for streaming video from your gaming PC to another screen, like your TV, a phone, or a Steam Deck. They include controller forwarding, but it assumes the controller and the screen live on the same device. Dish handles a different model:

The names nod at the same lineage. See why "Dish" and "Satellite".

Try it for yourself.

Five minutes from install to first input.

Download Dish