Steam Controller
-
Now that the SteamLink hardware is officially retired, and support for SteamLink at 4k60fps on a Raspberry Pi seems to be making progress, I thought I would sunset my hardware SteamLink and get a Pi 4 to do its job. It seemed logical therefor to install Retro Pi and be able to easily switch between EmulationStation and SteamLink, using the Steam Link controller for everything.
I don't have a 4 yet so I started testing on a 3 B+ that I have. I figured I'd spin RetroPi + SteamLink together with Steam Controller and see how things go, then move up to a 4.
Switching between EmulationStation and SteamLink is smooth and easy. Very well done on the setup scripts guys.
The Steam Controller is ... not great. What works:
- I'm able to install the
steamcontroller
driver and have EmulationStation recognize and be controlled by the Steam Controller if I use the dongle that came with the Steam Controller.
What doesn't:
- When I'm in SteamLink, the controller is detected as a Microsoft XBox 360 controller, not the Steam Controller (problematic b/c when playing games through Steam, having the extra buttons the Steam Controller provides is needed)
- When I power cycle the Steam Controller, the Pi loses the connection and it doesn't come back. I can restore it with a bit of effort: power off the Steam Controller, unplug the dongle, powering on the Steam Controller, and in the few seconds before the controller auto shuts off (due to not having its receiver plugged in), plug in the receiver.
- When the controller is in its "not detected" state, SteamLink doesn't see it either.
Thinking that maybe things would work better if the Steam Controller were paired with the Pi using BLE, I tried that route. Unfortunately my SteamController doesn't pair. Using the retropie_setup.sh scrip invariably I get the following message regardless of what security option I choose:
An error occurred connecting to the bluetooth device (Creating device failed: org.bluez.Error.AuthenticationCanceled: Authentication Canceled)
When I go back to "Display Registered & Connected Bluetooth Devices" though, I see the Steam Controller is "connected"
Registered Devices: D8:F0:EE:59:AD:1F SteamController D8:71:10:EC:67:1D SteamController Active Connections: < LE D8:F0:EE:59:AD:1F handle 64 state 1 1m MAST 1m MASTER
Watching
bluetoothctl
in an SSH session as I was testing there were plenty of messages, but no pairing, and the controller isn't seen by EmulationStation.I tried to pair the controller manually with
bluetoothctl
but again no bueno. Full output of my attempt is here; you can see me finding the controller, marking it as trusted, and pairing failing.So ... thoughts/advice/suggestions? I'm happy to test experimental/dev patches. I'm pretty good with Linux, though I'm not a programmer. I'd love to get this working and help contribute a special page on the Wiki for the Steam Controller.
Thanks in advance
- I'm able to install the
-
The newer rpi-5.4.y kernel includes the hid-steam kernel module that provides a native driver for the steamcontroller. With a little manual editing of es_input.cfg it works perfectly; without the CPU overhead and general clunkiness of the python based steamcontroller solution included with RetroPie.
Raspbian haven't updated the kernel package, but it can be done with rpi-update. Or by downloading the newest firmware and installing to /boot manually. Warning! When I first did rpi-update on my Pi4 they had recently switched to the 5.4 branch and it didn't add kernel7l to /boot and I had to add this file manually. I'm not sure if that's been fixed yet.
-
@Amorphous said in Steam Controller:
The newer rpi-5.4.y kernel includes the hid-steam kernel module that provides a native driver for the steamcontroller. With a little manual editing of es_input.cfg it works perfectly; without the CPU overhead and general clunkiness of the python based steamcontroller solution included with RetroPie.
Hey thanks!
I used rpi-update and EmulationStation detected the Steam Controller as a Steam Controller I was able to map some buttons. SteamLink detects the controller as a Steam Controller, and the controller re-connects after power cycling without issue.
That's most of my issues right there, so high-five to you sir.
Going back to "a little manual editing of es_input.cfg": How did you figure out the right values to go into es_input.cfg? mapping buttons through the EmulationStation UI is broken; left d-pad up/down is recorded as "Hat 0 Right" and "Hat 0 Left" respectively, hat left/right, and left d-pad left/right register as "already taken", etc.
Raspbian haven't updated the kernel package, but it can be done with rpi-update. Or by downloading the newest firmware and installing to /boot manually. Warning! When I first did rpi-update on my Pi4 they had recently switched to the 5.4 branch and it didn't add kernel7l to /boot and I had to add this file manually. I'm not sure if that's been fixed yet.
I didn't have this problem; just used rpi-update, let it complete, rebooted without issue.
-
@wmarler said in Steam Controller:
I didn't have this problem; just used rpi-update, let it complete, rebooted without issue.
rpi-update
will install the next (5.4) kernel branch. Note that usingrpi-update
is not recommended as a general update tool. -
@mitu said in Steam Controller:
rpi-update
will install the next (5.4) kernel branch. Note that usingrpi-update
is not recommended as a general update tool.Is there support in the current kernel branch for the hid-steam driver -- can it be built as a module maybe?
-
The
hid-steam
was added in the kernel as part of 4.18 and should be available in the next stable RPI kernel (4.19.1xx) - see https://github.com/raspberrypi/linux/issues/3344. -
Ah, ok, cool, thanks! I see there's no timeline on 4.19.1xx and that that's impossible to predict really, but it's nice to know that it's in the pipeline and "soon". Awesome to think that the steamcontroller driver can be soon deprecated from the driver section, and the Steam Controller will be expected to "Just Work".
So what is up with EmulationStation mapping buttons so bizarrely? This is what /opt/retropie/supplementary/emulationstation/scripts/inputconfiguration.sh created:
<?xml version="1.0"?> <inputList> <inputAction type="onfinish"> <command>/opt/retropie/supplementary/emulationstation/scripts/inputconfiguration.sh</command> </inputAction> <inputConfig type="joystick" deviceName="Wireless Steam Controller" deviceGUID="03000000de2800004211000011010000"> <input name="rightanalogup" type="axis" id="3" value="-1"/> <input name="pageup" type="button" id="6" value="1"/> <input name="rightanalogdown" type="axis" id="3" value="1"/> <input name="up" type="hat" id="0" value="8"/> <input name="left" type="axis" id="0" value="1"/> <input name="select" type="button" id="10" value="1"/> <input name="rightanalogleft" type="axis" id="2" value="-1"/> <input name="leftanalogdown" type="axis" id="0" value="-1"/> <input name="right" type="axis" id="1" value="-1"/> <input name="rightanalogright" type="axis" id="2" value="1"/> <input name="pagedown" type="button" id="7" value="1"/> <input name="y" type="button" id="5" value="1"/> <input name="x" type="button" id="4" value="1"/> <input name="down" type="hat" id="0" value="2"/> <input name="start" type="button" id="11" value="1"/> <input name="b" type="button" id="3" value="1"/> <input name="a" type="button" id="2" value="1"/> </inputConfig> </inputList>
I suppose it might look like I've pressed different buttons when configuring left d-pad up/down v. left/right, but I promise I haven't -- I can't understand why <input name="down" type="hat" id="0" value="2"/> but <input name="right" type="axis" id="1" value="-1"/>
-
Ok, whew, I think I've got it. Lots and lots of props to Rodrigo Rivas Costa for his hid-steam driver, this is a complicated device!
If you just want a copy-paste config, jump to the bottom code block in this post.
The Steam Controller can send different signals from the same button, and it takes a bit of finessing within the EmulationStation button-mapping system to grab them (that's what was going on above; I was in fact pressing different buttons when I promised that I wasn't). For example, squeezing a trigger sends an analog signal, and then clicking the button at the end of the trigger pull sends a digital signal.
Here are the different signals that the Steam Controller will send for the different buttons, and what you need in your
.emulationstation/es_input.cfg
for EmulationStation to react to them.Left D-PAD
The left D-PAD will send "hat" signals when you just touch it, and "button" signals when you press hard enough to actually click. Use this for touch-sensitive up/down/left/right:<input name="up" type="hat" id="0" value="1"/> <input name="down" type="hat" id="0" value="4"/> <input name="left" type="hat" id="0" value="8"/> <input name="right" type="hat" id="0" value="2"/>
And use this if you want to have to click for up/down/left/right:
<input name="up" type="button" id="17" value="-1"/> <input name="down" type="button" id="18" value="1"/> <input name="left" type="button" id="19" value="-1"/> <input name="right" type="button" id="20" value="1"/>
The left directional pad on the Steam Controller is SUPER sensitive, and I don't think there's a way to configure this sensitivity yet. Maybe this is a feature request for the steamctrl userspace tool ?
Left Analog Stick
The left analog stick sends two "axis" signals, one for up/down the other for left/right, and a "button" signal when you click it. The configuration is:<input name="leftthumb" type="button" id="13" value="1"/> <input name="leftanalogup" type="axis" id="1" value="-1"/> <input name="leftanalogdown" type="axis" id="1" value="1"/> <input name="leftanalogleft" type="axis" id="0" value="-1"/> <input name="leftanalogright" type="axis" id="0" value="1"/>
Right Analog Stick (The mouse-like touchpad)
EmulationStation doesn't use a mouse, but it'll happily respond to the "axis" and "button" signals you can send from the pad:<input name="rightthumb" type="button" id="1" value="1"/> <input name="rightanalogup" type="axis" id="3" value="-1"/> <input name="rightanalogdown" type="axis" id="3" value="1"/> <input name="rightanalogleft" type="axis" id="2" value="-1"/> <input name="rightanalogright" type="axis" id="2" value="1"/>
A, B, X, Y, Start, Select, Hotkey, Shoulders, Triggers, and Guards
Set these as follows:<input name="a" type="button" id="2" value="1"/> <input name="b" type="button" id="3" value="1"/> <input name="x" type="button" id="4" value="1"/> <input name="y" type="button" id="5" value="1"/> <input name="start" type="button" id="11" value="1"/> <input name="select" type="button" id="10" value="1"/> <input name="hotkeyenable" type="button" id="12" value="1"/> <input name="leftshoulder" type="button" id="6" value="1"/> <input name="rightshoulder" type="button" id="7" value="1"/> <input name="lefttrigger" type="hat" id="0" value="4"/> <input name="righttrigger" type="hat" id="0" value="2"/>
The "Guards" are the buttons on the back of the Steam Controller that no other controllers seem to have (if there's another name, I'll correct this post). They don't map to anything in EmulationStation, but they have button id's of 15 and 16.
As mentioned before, the Triggers also send an analog signal before you click the button at the end of travel. I don't know that there's a use for this signal in EmulationStation yet, and there isn't a use for me specifically, so I didn't try very hard to figure out if it's a "hat" or an "axis" signal, or what the signal identifiers are.
Gyroscopic input
I couldn't find a way to receive these signals in EmulationStation.Putting it all together
You might need to find your own deviceGUID, I'm not sure. Use EmulationStation to configure your controller once, map a button or two, then exit EmulationStation, and then and modify your.emulationstation/es_input.cfg
config file by hand.<inputConfig type="joystick" deviceName="Wireless Steam Controller" deviceGUID="03000000de2800004211000011010000"> <input name="up" type="button" id="17" value="-1"/> <input name="down" type="button" id="18" value="1"/> <input name="left" type="button" id="19" value="-1"/> <input name="right" type="button" id="20" value="1"/> <input name="a" type="button" id="2" value="1"/> <input name="b" type="button" id="3" value="1"/> <input name="x" type="button" id="4" value="1"/> <input name="y" type="button" id="5" value="1"/> <input name="hotkeyenable" type="button" id="12" value="1"/> <input name="leftshoulder" type="button" id="6" value="1"/> <input name="rightshoulder" type="button" id="7" value="1"/> <input name="leftthumb" type="button" id="13" value="1"/> <input name="rightthumb" type="button" id="1" value="1"/> <input name="leftanalogup" type="axis" id="1" value="-1"/> <input name="leftanalogdown" type="axis" id="1" value="1"/> <input name="leftanalogleft" type="axis" id="0" value="-1"/> <input name="leftanalogright" type="axis" id="0" value="1"/> <input name="rightanalogup" type="axis" id="3" value="-1"/> <input name="rightanalogdown" type="axis" id="3" value="1"/> <input name="rightanalogleft" type="axis" id="2" value="-1"/> <input name="rightanalogright" type="axis" id="2" value="1"/> <input name="lefttrigger" type="button" id="8" value="4"/> <input name="righttrigger" type="button" id="9" value="1"/> <input name="select" type="button" id="10" value="1"/> <input name="start" type="button" id="11" value="1"/> <input name="pageup" type="button" id="6" value="1"/> <input name="pagedown" type="button" id="7" value="1"/> </inputConfig>
-
That's very cool, thanks for digging this up.
Now, for the next step - how to create a correct.cfg
joypad auto-configuration for RetroArch (see examples in https://github.com/libretro/retroarch-joypad-autoconfig/tree/master/hid). -
I just rebuilt my RetroPie box and the hid-steam driver is still not present. Here's how to get it, if you want it. It compiles almost immediately on a RPi 4:
$ mkdir steam-build $ cd steam-build $ wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-4.19.y/drivers/hid/hid-steam.c $ wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-4.19.y/drivers/hid/hid-ids.h $ echo "obj-m += hid-steam.o" > Makefile $ make -C /lib/modules/`uname -r`/build/ M=$(pwd) $ sudo make -C /lib/modules/`uname -r`/build/ M=$(pwd) modules_install $ sudo depmod -a
EmulationStation will now detect it and you can map buttons as described in my previous post.
@mitu I would love to help contribute a correct
.cfg
joypad auto-configuration for RetroArch. This is what my/opt/retropie/all/retroarch-joypads/"Wireless Steam Controller.cfg"
looks like ... would the auto-configuration file just be a copy of that? I see the examples but I'm not sure how to turn my working .cfg into one of them.$ cat /opt/retropie/configs/all/retroarch-joypads/Wireless\ Steam\ Controller.cfg input_device = "Wireless Steam Controller" input_driver = "hid" input_vendor_id = "10462" input_product_id = "4418" input_a_btn = "2" input_b_btn = "3" input_x_btn = "4" input_y_btn = "5" input_up_btn = "17" input_down_btn = "18" input_left_btn = "19" input_right_btn = "20" input_l_btn = "6" input_r_btn = "7" input_l2_btn = "8" input_r2_btn = "9" input_select_btn = "10" input_start_btn = "11" input_enable_hotkey_btn = "12" input_l3_btn = "13" input_r3_btn = "1" input_l_y_plus_axis = "+1" input_l_y_minus_axis = "-1" input_l_x_minus_axis = "-0" input_l_x_plus_axis = "+0" input_r_y_plus_axis = "+3" input_r_y_minus_axis = "-3" input_r_x_minus_axis = "-2" input_r_x_plus_axis = "+2" input_save_state_btn = "7" input_menu_toggle_btn = "4" input_exit_emulator_btn = "11" input_load_state_btn = "6" input_reset_btn = "3" input_state_slot_decrease_btn = "19" input_state_slot_increase_btn = "20"
-
@wmarler said in Steam Controller:
@mitu I would love to help contribute a correct .cfg joypad auto-configuration for RetroArch.
We don't distribute configuration files for controllers - but the right place to submit it would be the upstream libretro project, at https://github.com/libretro/retroarch-joypad-autoconfig.
-
@wmarler first of all thanks to your work.
I encountered an issue when using the command make. So when I try to use the commands
make -C /lib/modules/uname -r
/build/ M=$(pwd)
$ sudo make -C /lib/modules/uname -r
/build/ M=$(pwd) modules_install
its something like :
make : Entering directory ........
make : *** No rule to make target ´ /build/´ . Stop
make : Leaving directory ´ /lib/modules .......I am quite new to linux on that level so I dont know what to do. Has somebody an idea.
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.