Skip to content

feat(rumble): forward MSG_RUMBLE to SDL controller (rumble + lightbar) - #14

Merged
emir-hasanbegovic merged 1 commit into
mainfrom
feat/rumble
May 14, 2026
Merged

feat(rumble): forward MSG_RUMBLE to SDL controller (rumble + lightbar)#14
emir-hasanbegovic merged 1 commit into
mainfrom
feat/rumble

Conversation

@emir-hasanbegovic

Copy link
Copy Markdown
Contributor

Summary

  • Adds the dish-side handler for the satellite's reverse-direction rumble message (MSG_RUMBLE = 0x0009).
  • SatelliteClient::processIncoming parses the wire format via a pure static parseRumbleMessage decoder; per-WifiConnection rumble handler resolves connId → slotId → deviceId via the ConnectionHub bindings; SDLGamepadBridge::applyRumble drives the matching SDL_GameController (SDL_GameControllerRumble + SDL_GameControllerSetLED for DS4 lightbar).
  • AppModel::installRumbleHandlers walks the pool on every poolChanged and attaches a handler to any new connection that doesn't already have one. Idempotent. Handler caching on WifiConnection survives reconnects.

Stacking

⚠️ This PR is stacked on feature/ui-overhaul-and-async-bind so the diff shows only rumble. Merge that PR first (or merge this into it directly).

Wire format

Documented in satellite/README.md#rumble-return-path:

ctrlIdx(u8)  strong(u16 BE)  weak(u16 BE)  durMs(u16 BE)  flags(u8)
[R, G, B] (u8×3 if flags bit 0 set)

Test plan

  • scripts/build.sh debug test — new tests/test_satellite_client_rumble.cpp (8 Catch2 cases) covers byte-layout decoding, stop requests, max magnitudes, lightbar tail, lightbar-flag-with-truncated-tail rejection, forward-compat trailing bytes, reserved flag bits, big-endian boundaries
  • Manual: pair with a satellite running this PR's companion server-side change; in any game that calls XInputSetState, verify a paired Xbox/DualSense controller buzzes
  • Manual: with a DualShock 4 paired and the satellite serving DS4-mode, verify the lightbar colour updates

Related

🤖 Generated with Claude Code

@emir-hasanbegovic
emir-hasanbegovic force-pushed the feature/ui-overhaul-and-async-bind branch from 0c808b5 to d97e5bd Compare May 14, 2026 13:18
Adds the dish-side handler for the satellite's reverse-direction rumble
message (MSG_RUMBLE = 0x0009). SatelliteClient::processIncoming parses
the wire format via a pure static parseRumbleMessage decoder, the
per-WifiConnection rumble handler resolves connId → slotId → deviceId
via the ConnectionHub bindings, and SDLGamepadBridge::applyRumble drives
the matching SDL_GameController.

* Wire format documented in satellite/README.md#rumble-return-path:
    ctrlIdx(u8) strong(u16 BE) weak(u16 BE) durMs(u16 BE) flags(u8)
    [R, G, B] (u8×3 if flags bit 0 set)
* SDL_GameControllerRumble passes the strong/weak magnitudes through
  verbatim (XInput scale matches). SDL_GameControllerSetLED is invoked
  when the satellite published a DS4 lightbar colour; both are silent
  no-ops on pads that don't support the feature.
* AppModel::installRumbleHandlers walks the WifiConnection pool on every
  poolChanged signal and attaches a handler to any new connection that
  doesn't already have one. Idempotent.
* WifiConnection caches the handler so it survives reconnects:
  markConnected re-installs it on the new SatelliteClient instance.
* parseRumbleMessage is exposed as a static helper so it can be unit-
  tested without driving a live socket. New Catch2 suite covers: byte-
  layout decoding, stop requests, max magnitudes, lightbar tail, lightbar
  flag with truncated tail, forward-compat with extra trailing bytes,
  reserved flag bits, big-endian boundary cases.

Stacked on top of feature/ui-overhaul-and-async-bind. PR base set to the
parent branch so the diff shows only rumble.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@emir-hasanbegovic
emir-hasanbegovic changed the base branch from feature/ui-overhaul-and-async-bind to main May 14, 2026 13:21
@emir-hasanbegovic
emir-hasanbegovic merged commit c334d64 into main May 14, 2026
@emir-hasanbegovic
emir-hasanbegovic deleted the feat/rumble branch May 14, 2026 13:21
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.

2 participants