mirror of
https://github.com/safijari/openpuck.git
synced 2026-11-03 22:30:22 +00:00
[PR #212] [MERGED] Add Original Xbox (Controller S) mode #243
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#243
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?
📋 Pull Request Information
Original PR: https://github.com/safijari/openpuck/pull/212
Author: @xbb
Created: 8/3/2026
Status: ✅ Merged
Merged: 8/21/2026
Merged by: @safijari
Base:
main← Head:feat/og-xbox-mode📝 Commits (5)
aa5244fCentralize custom USB class-driver registration789f37eAdd Original Xbox (Controller S) mode0f3ddf4Add Original Xbox mode to the config panel and README1914e37Add Original Xbox mode subsection in PROTOCOL.md3364f55Merge main into feat/og-xbox-mode📊 Changes
16 files changed (+914 additions, -29 deletions)
View changed files
📝
Makefile(+8 -2)📝
OpenPuck/OpenPuck.ino(+15 -14)📝
OpenPuck/config.h(+5 -1)📝
OpenPuck/controllers.cpp(+3 -0)➕
OpenPuck/mode_xbox_og.cpp(+804 -0)➕
OpenPuck/mode_xbox_og.h(+15 -0)📝
OpenPuck/mode_xinput.cpp(+2 -6)📝
OpenPuck/serial_console.cpp(+1 -1)➕
OpenPuck/usb_app_drivers.cpp(+12 -0)➕
OpenPuck/usb_app_drivers.h(+9 -0)📝
OpenPuck/usb_tx.h(+1 -0)📝
OpenPuck/webusb_config.cpp(+20 -0)📝
README.md(+2 -1)📝
docs/BUILD_AND_DEPLOY.md(+1 -1)📝
docs/PROTOCOL.md(+12 -0)📝
docs/index.html(+4 -3)📄 Description
Implements Original Xbox mode in
mode_xbox_og.{cpp,h}asmode 10: the puck presents itself as a Controller S, with rumble. It reuses the existing Xbox mapping tab, reporting LB/RB as the console's White and Black buttons. It is selectable from the WebUSB panel and it keeps the wake mouse and the WebUSB interface, so the panel stays reachable while the mode is active.Before accepting a controller, the console sends three XID requests over the control endpoint. These are vendor-type control requests, all of which TinyUSB routes to a single global callback that the Adafruit core already defines for WebUSB. A sketch can replace that callback wholesale, but it cannot extend it. If the requests are stalled, the console rejects the controller.
The build therefore links with
-Wl,--wrap=tud_vendor_control_xfer_cb, causing the linker to route every call through a wrapper. The wrapper handles XID requests while this mode is active and delegates everything else to the original callback, preserving WebUSB support. The flag is included in both build recipes and in thearduino-clicommand indocs/BUILD_AND_DEPLOY.md; omitting it causes the build to fail at link time.The same single-global constraint applies to TinyUSB's other application hook. XInput already uses
usbd_app_driver_get_cbfor its interface driver, and the new Original Xbox XID mode needs the same hook. Because the hook is a single global returning one driver table, it moves to a small sharedusb_app_drivers.cppthat returns both drivers. The XID driver is registered in every mode, but it only claims a0x58/0x42interface, which no other mode exposes, so existing behavior is unchanged.Tested on an Original Xbox: it enumerates, and buttons, sticks and rumble work in game. Switching out of the mode while plugged into the console is clean.
While testing on the console, switching away from PS3 mode leaves the puck unresponsive and powers off the connected controller after a short delay. Replugging the puck only recovers it if another mode switch is performed immediately. This is not caused by the new mode; it also reproduces without this change.
LLM-assisted implementation.
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.