mirror of
https://github.com/safijari/openpuck.git
synced 2026-11-03 22:30:22 +00:00
[GH-ISSUE #227] ESB metadata forwarding broken #97
Labels
No labels
pull-request
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
safijari/openpuck#97
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Leseratte10 on GitHub (Aug 9, 2026).
Original GitHub issue: https://github.com/safijari/openpuck/issues/227
The original Puck has four ESB interfaces (corresponding to the four connected controllers) that you can use to send messages directly to a connected Controller. OpenPuck doesn't seem to handle them correctly and instead answers them all with its own hardcoded data from identity.cpp.
To reproduce the error, pair your controller to an OpenPuck, then modify the pairing entry on the Puck (either using scpair or by exporting and importing the config) so that it no longer contains the serial number of the paired controller, so it looks like this:
Now connect the controller to the Puck, and then run "scpair.py list" from my fork in merge request #222
When you do that on an OpenPuck, it'll display the following:
Which means the controller name is wrong, and the controller firmware is wrong. Instead of showing name and firmware from the wirelessly-connected controller, it shows name and firmware from its own data.
When you instead run the same command on a Valve puck (or Steam Machine), it will display the following - so despite the fact that the puck's pairing record contains "MyController" instead of the serial number, it can still read and display the actual serial number of the paired controller:
Can you make OpenPuck behave like the original Puck, in that it should forward these requests to the controller to be answered?
This bug is most likely the root cause of #205 and #208, and the reason why Steam sometimes displays an invalid serial number in the controller settings, doesn't always correctly show the active slot, and doesn't always show "Steam Controller" for the pairing when looking at a Puck's pairings. Also, I would not be surprised if fixing this might also fix #214 and some of the jankiness around the controller haptics.
Looking at the source code in puck_hid.cpp in handleSet, there's a list "localAnswer" that marks the requests that should be answered by the Puck and not forwarded to the controller. 0xAE (read serial) and 0x83 (read attributes) is on that list, so you'll never be able to read the serial number or the attributes of a controller.
The comment for the 0xAE case explains why the behaviour is wrong - because it reads the serial number from the puck's bonding record, which may not always be the serial number of the connected controller. The original puck forwards both 0xAE and 0x83 to the controller if the request ID is set to 1, and only responds with its own data if the request ID is set to 2.
Same goes for 0x83 - the code doesn't actually forward the request to the controller, it just changes the PID from 0x1304 to 0x1302. Which makes all the metadata in there invalid (like, containing the Puck's firmware version instead of the controller's).
Also, request 0xED is supposed to return the controller's bond records, read from the controller over the wireless link. Not return the puck's bonding records. Right now, OpenPuck fakes a response with one slot only, which is the reason Steam doesn't correctly show a connected controller's pairings.
I tried to fix this, but I'm confused by the code. In puck_hid.cpp I can see a bunch of code that sends data to a wirelessly-connected controller by calling relayEnqueue - which for some weird reason seems to live in haptics.cpp - but I cannot find any code where it processes responses sent by the controller to these requests?
In general, most if not all requests sent with rid=1 are supposed to be forwarded to the controller, the controller will respond, and the puck will forward that response over USB. Only requests with rid=2 are supposed to be answered by the Puck itself.
@safijari can you shed some light here?