Skip to content

ReversePuck Deck app: run without sudo, clearer touchscreen UI, and a Game Mode AppImage - #327

Open
MisterAnderson91 wants to merge 2 commits into
safijari:mainfrom
MisterAnderson91:reversepuck-deck-app-appimage
Open

MisterAnderson91 wants to merge 2 commits into
safijari:mainfrom
MisterAnderson91:reversepuck-deck-app-appimage

Conversation

@MisterAnderson91

Copy link
Copy Markdown

ReversePuck Deck app fixes and a one-file AppImage: the app runs without sudo ./setup.sh, reliably hands the Deck's controls back, plays trackpad haptics and has a clearer touchscreen UI; as an AppImage it launches from Game Mode with no uv or network.

One of three independent ReversePuck PRs (firmware fixes, pairing commands, Deck app + AppImage). They touch separate files and can be merged in any order. Trackpad haptics need the firmware fixes PR; with older firmware everything else works and the haptics just don't arrive.

Summary

  • 7ddc806 Deck app: no sudo, reliable hand-back, haptics, new touchscreen UI
  • 0ad3c45 The fixed Deck app as a standalone AppImage (no install needed) that runs from Game Mode, built by CI for every change

Commits in detail

1. ReversePuck app: run without sudo, hand the Deck pad back reliably, per-pad haptics, touchscreen UI (ReversePuck/*.py, launcher comment, README)
These apply to the existing ReversePuck (uv) script as well as the AppImage in commit 2.

  • No sudo: SteamOS's Steam udev rule already gives the session user every 28DE device, the dongle's CDC included, so setup.sh isn't needed.
  • Robustness:
    • Never pick the Deck pad's own CDC (28DE:1205, /dev/ttyACM0) as the dongle.
    • grab() fails loudly instead of forwarding a dead neutral pad.
    • Hand the pad back on SIGTERM/SIGHUP (Steam's "Exit game").
    • Re-attach pad interfaces a crashed run left detached.
    • Keep the pad out of lizard mode while forwarding, using hid-steam's heartbeat. Its watchdog otherwise turns lizard mode, and its own haptic ticks, back on within seconds.
  • Haptics: plays the firmware's new PULSE frames with the Deck's 0x8F pulse (the Deck ignores the 0xEB rumble).
  • Touchscreen UI:
    • Tiles fill the screen (one, or two columns), with the state as the headline ("slot 0 - available - tap to connect"), and the wording is connect/disconnect.
    • The log is a fixed 4-line box.
    • Screen timeout: when a forward's link comes up, the screen counts down 5 s and goes black; a tap keeps it on, and later taps toggle it. Hold still disconnects whether the screen is on or black.
    • Touches are taken from finger events only, since SDL also synthesises a mouse click for each.
  • Instructions: setup.sh is only needed off SteamOS.

2. ReversePuck: Steam Deck app as an AppImage that runs from Game Mode, built by CI (ReversePuck/packaging/, new workflow, READMEs)
Builds on commit 1: it packages that app, unchanged.

  • AppImage: ReversePuck/packaging/build-appimage.sh bundles a portable Python 3.12 with the manylinux wheels for pygame, pyserial and pyusb. It uses uruntime (pinned, SHA-256 checked) instead of the stock runtime: Steam starts Game Mode games with no_new_privs, which stops fusermount, and the stock runtime then just exits. uruntime falls back to extract-and-run.
  • CI: .github/workflows/reversepuck-appimage.yml builds the AppImage for every push/PR touching ReversePuck/ (an Actions artifact) and attaches it to releases.
  • READMEs: how to get and use the AppImage; the uv script stays the alternative.

Testing

Hardware: Steam Deck OLED with a ReversePuck (Pro Micro nRF52840), an OpenPuck on 0.9.51, and the host running Steam on macOS.

  • The AppImage launches from Game Mode with no launch options, and the pad is handed back on exit.
  • Trackpad haptics arrive within ~0.4 s of connecting and tick on the correct pad (with the firmware fixes PR).
  • The screen timeout and hold-to-disconnect were checked on the Deck and in a headless pygame test.
  • The AppImage workflow passes on this branch.

Not tested: the uv script from Game Mode, and hosts other than macOS.

🤖 Generated with Claude Code

MisterAnderson91 and others added 2 commits October 25, 2026 13:58
…er-pad haptics, touchscreen UI

Running without sudo and handing the Deck pad back
- SteamOS already grants the session user every 28DE device (Steam's uaccess
  rule), so setup.sh isn't needed there. Never pick the Deck pad's own CDC
  (28DE:1205, /dev/ttyACM0) as the dongle.
- grab() fails loudly and rolls back when the DeckState interface can't be
  claimed, instead of forwarding a dead neutral pad.
- Exit cleanly on SIGTERM/SIGHUP (Steam's "Exit game") so the pad is handed
  back, and re-attach pad interfaces a crashed run left detached.
- Keep the Deck pad out of lizard mode while forwarding (hid-steam's
  heartbeat: clear digital mappings + both trackpads TRACKPAD_NONE every 2 s);
  its watchdog otherwise turns it back on within seconds.

Haptics
- Play the firmware's PULSE frames as the Deck's 0x8F haptic pulse (the Deck
  ignores the 0xEB rumble). Rumble no longer drops repeated identical "on"
  states and switches itself off when they stop.

Touchscreen UI
- Tiles fill the space between header and log: one tile alone, else two
  columns with the left taking the smaller half. Each tile's headline is the
  state ("slot 0 - available - tap to connect"), fitted in the largest bold
  font that fits; the serial is the small print.
- Say connect/disconnect instead of forward/stop throughout.
- The firmware log is a fixed 4-line box at the bottom.
- Screen timeout: when a forward's puck link first comes up, the screen counts
  down 5 s and goes black (OLED pixels off); a tap during the countdown keeps
  it on. After that a tap toggles the screen. A hold disconnects whether the
  screen is on or black; a hold let go early leaves the screen as it was.
- Take touches from FINGER events only: SDL also reports each touch as a
  synthetic mouse click, which made every release count twice.

Instructions: setup.sh is only needed off SteamOS; the lizard-mode keep-alive
and hand-back are described in the README notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…built by CI

One file to add to Steam as a non-Steam game and launch from Game Mode or
Desktop Mode: no uv and no network.

- ReversePuck/packaging/build-appimage.sh bundles a portable Python 3.12 with
  the manylinux wheels for pygame, pyserial and pyusb; builds on macOS or
  Linux.
- uruntime (pinned v0.8.1, SHA-256 checked) instead of the stock runtime:
  Steam starts Game Mode games with no_new_privs, which stops fusermount, and
  the stock runtime then exits; uruntime falls back to extract-and-run.
- The log goes to ~/.local/state/reversepuck/openctrl.log.
- .github/workflows/reversepuck-appimage.yml builds the AppImage for every
  commit and PR touching ReversePuck/ (Actions artifact) and attaches it to
  releases.
- READMEs: how to get and use the AppImage; the uv script stays the
  alternative.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant