The project's README from github.com/jmedina21/deck-as-controller. As one markdown file: README.md.
https://github.com/user-attachments/assets/07d785e7-5d3b-4eb8-ae28-92e55b4d503f
A Decky Loader plugin that turns your Steam Deck into a controller for your Mac, iPad or PC, wirelessly over Bluetooth or wired over a USB cable. Nothing needs to be installed on the other device: the Deck shows up as a PS5, Xbox or Steam Controller.
This is still a very early build, expect latency and connection issues, specially with untested devices.
Developed on a Steam Deck OLED (Decky Loader 3.2.9 and SteamOs 3.8.28) with a Mac M4 running macOS 27. See Tested devices for what others have tried.
Independent project. Deck as Controller is developed independently and is free. It isn't affiliated with, endorsed by, or sponsored by Valve Corporation.
deck-as-controller.zip from the releases page.deck-as-controller.zipWhile connected, the Deck's controls go to your device:
| On the Deck | Does |
|---|---|
| Tap ⋯ (or the screen) | Turn the Deck screen on or off |
| Hold ⋯ for 2 seconds | Stop and give the Deck its controls back |
Switching controller types: your device remembers the Deck as the type it was paired as. To switch, remove the Deck from your device's Bluetooth settings, choose the new type, tap Pair a new device, and pair again.
Over a USB-C cable the Deck is a wired PS5 or PS5 Edge controller: no pairing, and input arrives much more steadily. On a Mac, the longest gap between updates was 14 ms over USB, against 80-140 ms over Bluetooth, and tested games felt lag-free.
While USB mode is on, USB drives, hubs and docks plugged into the Deck may not work, the Deck can't boot from USB, Windows installed on the Deck loses USB, and the Deck charges slowly from a computer. To go back, tap Turn off USB mode in the wired view (the Deck restarts again).
Switching USB mode from the plugin works on the Deck OLED with BIOS F7G0114. On other BIOS versions the plugin shows how to turn it on in the BIOS instead: with the Deck off, hold Volume + and press Power, open Setup Utility, then Advanced → USB Configuration → USB Dual Role Device → DRD.
On a Mac, PS5 Edge is the best all-round choice. Tested results:
| PS5 / PS5 Edge | Xbox Elite | Steam Controller | |
|---|---|---|---|
| Steam and games played through it (e.g. Baldur's Gate 3, Hades) | ✅ | ✅ | ✅ |
| Mac games that read controllers directly (e.g. Hollow Knight: Silksong) | ✅ | ❌ not detected | ❌ not detected |
| Rumble from Steam (Steam's test page, Steam Input games) | ❌ | ✅ | ✅ |
| Rumble from Mac games using Apple's controller support | ✅ | ✅ | – |
| Back buttons | PS5 Edge | Steam only | ✅ |
Steam Controller is for playing through Steam (including Steam on a Linux or Windows PC). The Deck has the same controls as the 2026 Steam Controller, so Steam sees both sticks, both trackpads as separate pads, the four back buttons, gyro and stick touch, and you configure them with Steam Input like a real one. Rumble and trackpad haptics come from Steam. Games that don't run through Steam won't recognize it: on a Mac that includes native games like Hollow Knight and Silksong, because macOS has no support for the Steam Controller and Steam can't pass it on to them. Tested with Steam on a Mac and on a Linux PC.
| Deck | PS5 / PS5 Edge | Xbox Elite |
|---|---|---|
| A B X Y | ✕ ○ □ △ | A B X Y |
| View / Menu | Create / Options | View / Menu |
| Steam | PS | Xbox |
| Trackpad click | Touchpad click | – |
| L4 / R4 | Edge left / right Fn | Paddles P3 / P1 |
| L5 / R5 | Edge left / right paddle | Paddles P4 / P2 |
| ⋯ | reserved for the plugin | reserved for the plugin |
As a Steam Controller every control keeps its own name (A B X Y, View / Menu, Steam, L4 / R4, L5 / R5, both trackpads); only ⋯ stays reserved for the plugin.
Reports from the developer and from users. Something missing or different for you? Open an issue.
| Deck | Connected to | Controller type | Result | Source |
|---|---|---|---|---|
| OLED | Mac (macOS 27), Steam | all four | ✅ Works, see Which type to pick | @jmedina21 |
| OLED | Mac (macOS 27), native games | PS5 / PS5 Edge | ✅ Works | @jmedina21 |
| OLED | iPad Mini 7 (iOS 27) | Xbox Elite | ✅ Works | @jmedina21 |
| OLED | Mac (macOS 27), USB cable | PS5 / PS5 Edge | ✅ Works in Steam and native games, including back buttons, rumble and replugging | @jmedina21 |
| – | Steam Frame | all | ✅ Works | #3 |
| LCD | Linux PC (NixOS) | PS5 Edge | ✅ Works, including trackpads and back buttons. Remove any old pairing on both sides first. | #4 |
| – | Linux PC (CachyOS), Steam | Steam Controller | ⚠️ Works for one user; another's pairing failed with an authentication error | @SrStylus, #2 |
The plugin's backend runs a small daemon with the Deck's system Python:
/run) that frees the HID
channels and gives the Deck a gamepad identity, then serves the Bluetooth HID profile itself.
Stopping the plugin, or rebooting, restores the stock setup.AmdSetup UEFI variable), which takes
effect at the next boot. The original variable is backed up first.py_modules/sdcd/profiles/ defines each controller type: its Bluetooth
identity, HID descriptor, input encoding and rumble parsing.pnpm install
scripts/deploy.sh deck@<deck-ip> # build and install over SSH (needs passwordless sudo on the Deck)
scripts/package.sh # build out/deck-as-controller.zip
To log what the host sends (rumble, setup requests), run sudo touch /run/sdcd-debug on the
Deck before turning the plugin on; the output appears in Decky's plugin log.
The plugin switches USB mode by changing one byte in the AmdSetup UEFI variable, and that
byte's position can differ between BIOS versions. To find it on yours (Desktop Mode, Konsole):
cat /sys/class/dmi/id/bios_version.sudo cp /sys/firmware/efi/efivars/AmdSetup-3a997502-647a-4c82-998e-52ef9486a247 ~/amdsetup-xhcils /sys/class/udc shows dwc3.1.auto, and save another
copy as ~/amdsetup-drd.cmp -l ~/amdsetup-xhci ~/amdsetup-drd. It should print a single line such as
229 0 1. The offset is that first number minus 5 (cmp counts from 1, and the file starts
with 4 attribute bytes), so 229 means 224. Also note the file size (ls -l)."<version>": <offset> to DRD_OFFSETS in py_modules/sdcd/usb.py, or open an issue
with the version, the cmp output and the file size. If the size isn't 1474 bytes, mention
it: the plugin checks the size before writing.Only map a version when exactly one byte differs. The menu itself is the Setup variable, which
the firmware doesn't let the OS write, so its offset alone isn't enough. You can still use it to
cross-check: the firmware images in /usr/share/jupiter_bios/ contain the BIOS menus, and
running UEFIExtract and
IFRExtractor-RS on the SetupUtility module
shows "USB Dual Role Device" and its Setup offset (0x227 on F7G0114).
Contributions are welcome: bug reports, pull requests, and test results on devices we haven't tried yet (Windows, Android, other Linux distributions, other macOS and iPadOS versions).
When reporting a problem, please include your Deck model, the controller type you picked, the
device you connected to, and the plugin log from ~/homebrew/logs/deck-as-controller/ on the
Deck. To capture what your device sends to the Deck, see the debug tip under
Development.
Released under the MIT License.
Steam and Steam Deck are trademarks of Valve Corporation. PlayStation, DualSense and PS5 are trademarks of Sony Interactive Entertainment. Xbox and Xbox Elite are trademarks of Microsoft. Mac and iPad are trademarks of Apple. These names are used only to describe compatibility; this project isn't affiliated with or endorsed by any of these companies.
The plugin changes the Deck's Bluetooth setup and takes over its built-in controller while it runs. Both are restored when you turn it off or reboot. Turning on USB mode changes a firmware setting, which stays until you turn it off in the plugin or change it in the BIOS. Use it at your own risk.