NIGHTLY panel built from ripps-d19b90db (main). It can expect firmware newer than the last release; for a promoted build use the stable panel.
OpenPuck SC2 puck · WebUSB disconnected Firmware— Mode— …

First connect uses the Chrome/Edge device picker; reconnects are automatic. If the picker is empty, quit any app holding the device or replug.

Clone pairings from an official puck

Version

Firmware build
—
Saved storage
—
Paired controllers
—
Status protocol
—
Panel update
—

This section reflects the connected puck. Reconnect after flashing or changing modes to verify what is currently running.

Controller

RF link
Battery
—
Signal
—
Fires the controller power-off (0x9F "off!", x3) — the same path Steam's "turn off controller" and host-suspend use. Watch the link status to see it disconnect.
If the controller's haptics get stuck/buzzing, this re-inits them (same as pressing Steam).

Radio

Selected controller

Polls/s
—
Delivered
—
Fails/s
—

Fails: CRC errors · no reply · relay drops.

Puck

RF channel
—
Relay/s
—
Link heals/s
—

All controllers

Delivered
—
New reports
—
Polls/s
—
Fails/s (crc · no reply)
—

Puck health

Loop
—
Clock LF / HF
—
µs per ms (ideal 1000)
—
usbd stack free (words)
—
Loop period
—
Slowest stage
—
Poll period act/want
—

Polls/s ≈ 250 expected; it's capped by Loop period (≈4000 µs needed). "Slowest stage" is the loop section eating the most time per iteration.

Last reset

Cause
—
Chip reset flags
—

—

—

Stability test

— Buzzes the controllers every 10 s (keeps them awake) and times how long the puck stays up. On a reset it records the uptime and shows it by Last reset; it auto-resumes after the puck reconnects. The count is kept in this tab (a page refresh clears it).

Preview data (debug)

Lays made-up data over the real status so the layout can be checked without a second controller or a crash. Nothing is sent to the puck; turn both off to see the real values again.

USB mode

Switching reboots the puck and re-enumerates USB (~2 s). WebUSB works in every mode except PS3 and the single-HID PlayStation modes; in Steam and Lizard it works even with Steam running (Chrome claims the vendor interface; Steam keeps the HID slots). Switch HORIPAD + WebUSB is PC-only.

Startup & identity

Off (default): every restart / fresh reconnect boots into Steam mode. On: remembers the last mode you selected.
On: OpenPuck presents itself as a Steam Machine's internal receiver (28DE:1305) instead of a Steam Controller Puck (28DE:1304). Takes effect on the next reboot.

Mode shortcuts

Hold the selected modifier (Quick Access or all four back paddles ) plus a face button or D-pad direction to switch mode without the WebUI. A is always Steam — that is the way back out of any mode. B / X / Y and D-pad directions are configurable (defaults: B=Lizard, X=Xbox, Y=Switch Pro). Modifier + trackpad click toggles the touchpad.

Face buttons
D-pad

This puck's firmware predates the D-pad chords — update it to configure them.

Button mapping

Each controller type only offers buttons that exist on that controller, and a dot on its tab marks the type of the current mode. Steam mode does its own remapping, so it has no tab here.

Lizard (desktop) bindings

Keyboard, mouse & media bindings for Lizard mode: each binding maps a controller input to a desktop action, checked top to bottom. Steam-mode seamless lizard (Steam closed) keeps the built-in default behavior and is not affected by this map. Pointer speed and glide are in Trackpad mouse below. Edits apply after Save to device. With current firmware there are three profiles of bindings, chosen below.

This puck is in —. Its firmware can edit the lizard map only in Lizard mode; update the firmware to edit it from any mode.

The puck isn't in Lizard mode right now. Saved changes take effect the next time it is.

—unsaved changes

—

Trackpad feedback

This puck's firmware predates the Lizard trackpad haptics — update it to set them.

For Lizard mode; Steam mode's lizard (Steam closed) leaves the trackpads to Steam. On plays the controller's own ticks and clicks at a fixed strength; choose a tick spacing and the puck plays both itself, at the Tick and Click strengths. Clicks only has no ticks and the puck pulses each click at the Click strength.

Trackpad mouse

Right-pad cursor in Steam-mode lizard (Steam closed) and in Xbox mode. Sensitivity is a divisor — lower = faster pointer. Glide = how long the cursor coasts after a flick. One setting, shared by the Xbox and Lizard profiles.

A short pulse on the clicked pad, once per press, in either trackpad D-pad mode. Independent of Trackpad haptics above.

Corrected (default) trims the gyro so Switch Pro mode matches a genuine Pro Controller and Steam mode (roll ×0.8, pitch/yaw ×0.9). Legacy sends the raw axes untrimmed — the pre-fix behavior, if you preferred the faster feel or tuned your in-game sensitivity around it.

This puck's firmware predates the gyro-mapping setting — update it to configure it.

In Switch Pro mode the game's HD rumble plays at the game's frequencies: both bands as one waveform on each grip, and the high band as tones on the trackpads. Grip rumble strength and HD trackpad strength scale them separately. Trackpad output is capped at −15 dB from 250–300 Hz, with gradual transitions outside that range.

Triggers

Emulated modes only; Steam mode passes the triggers to Steam Input untouched. Travel up to the deadzone reads as released, and travel at or past "Full press at" reads as a complete pull. Lower "Full press at" if a game made for DualSense resistive triggers doesn't register a full pull (firing while aiming, for example).

Rumble

Buzzes every connected controller for half a second at the current mode's strength.
A tone on the grips that pans left, right and back, twice over 4 seconds. It should feel equally strong all the way across. In Switch Pro mode it plays with the Switch tab's haptic style; in other modes it plays as Wave. A controller already playing DualSense audio haptics is skipped.

Rumble follows the mode: HD rumble in Switch Pro mode, normal rumble everywhere else. Turn rumble on or off and set its strength per mode in Button mapping; HD trackpad strength is on the Switch tab. Grip rumble strength scales a game's rumble. In Switch Pro mode that includes HD rumble's Wave style, which stops getting stronger at 100%: past that the grips distort and grind, so higher strengths only apply to the Tone, Split and Rumble styles. DualSense audio haptics don't use it: their strength is in the Haptics card on the DS5 tab.

This puck's firmware predates the rumble-shaping settings — update it to configure them.

Motion sensor (IMU)

Orientation from
—
Accel x y z
—
Gyro x y z
—
Controller quaternion w x y z
—

Shows the controller selected on the Status page. Recenter turns the model to face forward from how you're holding it now.

Accel (raw): —

The controller streams motion data only when asked. Emulated modes turn it on when a controller connects; Steam and Lizard modes don't, so there the reading stays at zero until you turn it on here. Applies to every connected controller.

Raw SC2 accel (before scaling). This controller is a ±2 g sensor (~16384 = 1 g); the Switch report divides it by 4 to present the genuine ±8 g (4096 = 1 g) scale so the console's gravity-correction engages and the gyro stops drifting.

3D controller model from Valve's Steam Controller CAD files (simplified), licensed CC BY-NC-SA 4.0. OpenPuck is not affiliated with Valve.

RF recovery & channel journal

Active channel
—
Recovery target
—
Startup channel
—
Ambient survey
—
Journal sequence
—
Journal writes this boot
—
Handoff status
Idle
Journal builder
Idle

OnChannelMHzJournalWorstMeanConfidenceTrialsPenaltyAmbientRecentActions

Status LED

SuperMini / Nice!Nano: 24, Nordic PCA10059: 11, Feather: 3 or 4 (255 = None)
Optional second LED pin (255 = None)
Flashes the configured pin(s) for 2 seconds to visually identify connected LEDs.

If testing your pin does not light up an LED, note that some boards have an onboard battery charger IC (TP4054) that pulses when no battery is attached and cannot be controlled via GPIO.

This puck's firmware predates the status LED settings — update it to configure them.

Backup & clone

Save this puck's controller pairings and every setting to a file, then restore them onto another puck. The other puck becomes a clone — any controller paired to this one connects to it with no re-pairing. (Also a plain backup: re-import after a factory erase to get everything back.)

Import overwrites all pairings and settings on the connected puck, then reboots it (~2 s — reconnect after). Tip: pair every controller to one puck, export once, then import onto each spare.

Clone from an official puck

Copy the controller pairings off a Valve puck so those controllers connect to this OpenPuck with no re-pairing. Works with one USB port: 1. plug in the official puck and read it, 2. unplug it, plug in the OpenPuck, Connect, and write. With both plugged in, the browser lists two identical "Steam Controller Puck" entries in step 1 — pick either; if it's the OpenPuck, the panel says so and you pick the other. Existing pairings and settings on the OpenPuck are kept.

—

macOS: reading the official puck needs Chrome in System Settings → Privacy & Security → Input Monitoring (restart Chrome after enabling it). The puck's interfaces include a keyboard, so macOS asks for this — the page can only reach the puck's vendor channel, never keystrokes. You can switch it off again afterwards.

Maintenance

Reboot ONCE with the CDC serial console enabled (WebUSB goes away for that boot); auto-reverts on the next boot
Reboot into serial DFU (adafruit-nrfutil), then replug
Reboot into the UF2 mass-storage bootloader; drop a .uf2 on the drive
Settings and pairings only: reformats the settings storage and reboots on defaults. The firmware and the RF channel journal stay. Re-pair the controller afterwards. Cannot be undone.
Everything: erases the flash itself, so the firmware, settings, pairings and RF channel journal are all gone. The board then mounts as a blank UF2 drive until you drop an OpenPuck .uf2 on it. Use it when a factory erase doesn't help, such as pairings or settings that won't stay saved. Cannot be undone.

Firmware update (beta)

Updating from this page is still being tested and may not work correctly.

  • A bad image or an interrupted update can leave the puck needing a manual recovery: double-tap reset and drag a .uf2 onto the UF2BOOT drive it mounts.
  • A different build can change or reset settings. Export a backup first (Device, Backup & clone) if your puck is paired and configured.
  • The panel and the puck disconnect while the update applies.

Your choice is remembered in this browser.

Panel updates not supported by this firmware

Update from a local file

Drop a .uf2 file here — or click to browse
no file selected
The image is streamed over WebUSB into spare flash, verified on the puck, and applied on an automatic reboot. Nothing is armed until it verifies — a failed or interrupted transfer leaves the running firmware untouched, and even a power cut during the apply only leaves the puck in its UF2 bootloader for drag-and-drop recovery.

Update from a release

Official builds from github.com/safijari/openpuck/releases  ·  installed: —
loading…

Factory reset flashes the -factory-reset build of that version: on its first boot it wipes ALL settings and the controller pairing (you must re-pair), then behaves like the standard build. Use it to recover from a bad config or stale bond. Debug flashes the -debug build: it keeps your settings and pairing, adds the Capture view and diagnostic counters, and uses about 25 KB more RAM. Flash the standard build to go back.

Firmware updates are enabled in this browser.

Hang log

One row per reset: uptime before it, reason, the stuck loop stage and captured PC (when the watchdog ISR could run), and usbd stack free. Accumulates across resets in this tab — a page refresh clears it. Pair with Test stability above for unattended runs.

no resets logged yet

    

Loop-state trail

Every change of the Loop pill, timestamped — stall episodes, live wedge reports, heartbeat loss (hard wedge, USB silent), recoveries, disconnects and the reset cause on reconnect — so an unattended hang is recorded even if you weren't watching. Saved in this browser (localStorage): it survives page refreshes and device reboots, and clears only with the button.

no events yet
—

Flight recorder

The trail of events the firmware recorded in the seconds before its most recent watchdog hang — the ring survives the reset in .noinit RAM (like the hang PC), so it's the post-mortem of what wedged the board. Loads automatically after a hang reconnects; click to reload. Same data the console FR command prints.

no trail loaded
—

Capture — host → controller commands

The firmware logs everything from boot into a big RAM ring: Steam's writes (ifN), the frames we transmit to the controller (TX→ctlr), and RF LINK UP/DOWN edges. For the reconnect buzz: trigger it (it appears moments after the puck boots / the controller reconnects), then connect here and click Dump from boot — the trigger is still in the ring. (Only present in a logging build, -DOPK_LOG=1.)

Dump streams the whole ring (oldest→newest) and then keeps live-updating until you press Stop. cmd is the command/report byte, then the raw bytes.


    

Firmware update

…