Conversation
…fier Adds the SdlGamepadSpecifier enum variant, schema component, protocol YAML (two 0-65535 vibrate features, low/high motors), and the regenerated device config (v5.43). Structural inspiration: chiefautism's abandoned PR #860.
Stateful two-motor handler mirroring the XInput protocol: every vibrate command carries the full motor state as two u16 LE values on Tx, so each write is a complete command with no batching step.
Cross-platform (Windows/macOS/Linux) gamepad rumble via SDL3, statically built from source. One process-lifetime thread owns the SDL context and multiplexes all gamepads addressed by SDL3 instance ID; discovery is on-demand enumeration and removal is connected-state polling - the thread never pumps SDL events. Rumble is armed finitely (60s) and refreshed before expiry so one-shot commands hold indefinitely. Includes the Phase 0 threading spike example (headless init + no-pump enumeration on a spawned thread). Joins the workspace as both a member and default member so plain cargo build compiles it on all three OSes. Structural inspiration: chiefautism's abandoned PR #860.
Registered in the v1-v4 embedded/json lists. v0 is excluded with a comment: SingleMotorVibrateCmd broadcasts one speed to all motors and cannot express the per-motor addressing this case verifies. Test harness gains an sdl-gamepad specifier branch (Tx-only endpoints) alongside the BLE default.
Registers the SDL gamepad communication manager on all platforms (no OS gate, unlike XInput) and logs a warning on Windows when both gamepad managers are enabled, since the same physical controller may then appear as two devices. Flag plumbing, default-false options, and the registration decision are unit-tested.
Non-default feature (SDL3 source build is too heavy for default library consumers): enabling it registers the SDL gamepad manager, cross-platform with no OS gate. Manager registration is refactored into a named-returns helper asserted by a feature-gated test.
On all three OS matrix entries: run the in-process client tests with --features sdl-gamepad-manager, assert via cargo tree that sdl3 is absent from default features and present with the feature, and run the SDL3 headless threading spike example (automated half of the Phase 0 gate; CI runners have no controllers, so an empty gamepad set passes).
…devices SDL3 on macOS routes wired gamepads to GCController (MFI) by default: the hidapi device drivers decline wired pads (DevSrvsID paths) while MFI is enabled, and GCController discovery only fires via Cocoa runloop notifications - which a headless, no-video process never spins. Result: zero gamepads ever discovered, even on the main thread with event pumping. Verified against SDL 3.4.14 source (SDL_PLATFORM_MACOS && SDL_JOYSTICK_MFI guard in SDL_hidapi_xboxone.c) and on hardware: with SDL_JOYSTICK_MFI=0 the wired Xbox One S enumerates via hidapi and set_rumble succeeds. iOS keeps the MFI default (GCController is the only backend there). The spike example mirrors the factory's platform policy. Windows discovery failure remains under investigation (likely analogous WGI behavior; needs an on-hardware SDL_LOGGING=3 run).
On-hardware diagnosis (wired Xbox One S, USB): with the MFI=0 hidapi policy, wired pads enumerate but rumble silently fails - Apple exposes only read-only shortened HID reports for them, and the working path (GCController/CoreHaptics) requires a main-thread runloop this architecture deliberately does not host. SDL2 has the same Apple-side guard, so a version switch would not help. Per operator decision, v1 is Bluetooth-only on macOS: scan probes each candidate's SDL connection state and skips Wired pads with a logged explanation pointing users at Bluetooth pairing. Verified on hardware: SDL reports the wired pad as connection Wired. Bluetooth pads and all of Windows/Linux are unaffected. The spike example now enables verbose SDL logging and prints each pad's connection state, so a single run is a complete diagnostic - this is the tool for the still-open Windows zero-device diagnosis (likely the analogous XGIP/WGI claiming dance).
On-hardware validation (Bluetooth DualSense, macOS) showed rumble stops after a few seconds despite the 60s arm - some controllers do not honor long durations. Re-sending the current non-zero command every second keeps the effect alive; the long finite arm stays as a safety net if a keepalive is missed. Same refresh_decision machinery, tighter interval.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implement support for SDL3, removing the xinput and hid managers at the same time (as SDL3 will handle those)