I made a script which utilizes USBIP to expose the Steam Deck’s controller to the network, then connect to it from the desktop.
I love the Steam Deck’s controls: dual-analog, trackpads, 4 rear buttons, and Valve’s incredible input configurator. While Valve has announced plans for a standalone controller, we’ve been in the dark ever since. Not a word.
I initially had Sunshine (game streaming server/remote desktop) set up to act as a controller but Sunshine shows the inputs from Moonlight (client program) as a plain xbox controller, meaning limited access to the controller configuration and any configurations are universal instead of per-game. This solution felt wasteful due to video/audio encoding and decoding, when all I really want is the controller. Same goes for the built-in Steam stream features.
I started looking into solutions and found USB/IP. The Steam Deck’s controller is simply a USB device, which USB/IP can bind to.
This works best on decks with aftermarket operating systems on them as my setup requires a writiable root partition. I use CachyOS handheld and as far as I know, there’s nothing that SteamOS has that this version of CachyOS doesn’t.. other than being a machine you can actually administrate.
On both the server and the client, members of group wheel should be allowed
to run usbip without entering a password so the connections are made
seamlessly:
# sudo EDITOR=nano visudo
then add the following on a newline in the file:
%wheel = (root) NOPASSWD: /usr/bin/usbip
This is optional of course, because you could type (tap) your password in every time.
I also generated a ssh key for my deck and put it on my desktop for passwordless authentication so I can do everything in one script.
I do have concerns regarding security when doing so as the deck being a portable device leaves it more prone to theft. I plan on discussing these concerns more in a future post.
The deck will go to sleep after some specified time. I need a way to prevent this. You could really use any foreground program here since all it needs to do is “pause” the execution of the script from until your selected program closes.
Something like mpv looping any video you’d like would work great, you’d just need a way to stop playback and close mpv (though this brings back the video decoding/battery problem I was trying to avoid in the first place)
I wrote myself a custom one. It’s a small C program using raylib that has a
DVD-esque bouncing logo to indicate to the user that the deck is in “controller
mode”. This program doesn’t guarantee a client is connected, rather it simply
displays a “screensaver” while waiting for touchscreen input. On such input it
exits.
Unfortunately my program doesn’t inhibit automatic system suspension as I had hoped, but it does black-out the display, which minimizes distraction and saves on battery (at least on the OLED model). I’m sure theres something I could do better to inhibit sleep, but in the meantime I launch the script in desktop mode and manually block suspension by toggling it in KDE’s power/battery tray-menu.
The final, albeit simple, script that is run on the Deck is as follows:
#!/bin/bash
sudo usbip bind -b 3-3
ssh navi doas usbip attach -r cirno -b 3-3
/usr/local/bin/steamdeck-inhibitor
ssh navi doas usbip deatach -p 00
sudo usbip unbind -b 3-3
Where navi is my desktop and cirno is my deck (Tailscale’s MagicDNS handles
name resolution). If you’re doing this yourself you’ll have to change those
hosts.
Ah, I also use a freakish mismatch between doas on my Gentoo boxes, and sudo
on pretty much everything else. Swap/replace these commands as necessary.
If you want game streaming with Sunshine and using USB/IP you can replace
the steamdeck-inhibitor line with whatever command you use to launch
Moonlight. I’ve done so myself, but I haven’t figured out an equally elegant
way to start and stop Sunshine sessions. It’s scuffed, but this is what I do currently:
Whereas with the steamdeck-inhibitor program:
This setup is great because you get your cloud-synced, per-game Steam input configurations and comparatively low battery consumption to using Sunshine as a controller. I haven’t measured, but on my home network there is little latency. None that I notice as a human.
Occasionally the controller disconnects. Not pleasant during an Elden Ring session but luckily it hasn’t done so during any tough fights, just during the intermediate areas and travel.