Skip to content

Automatically reconnect Switch 2 controllers after long pauses (opt-in) - #3

Merged
jmonster merged 2 commits into
masterfrom
feature/switch2kit-auto-connect
Sep 18, 2026
Merged

jmonster merged 2 commits into
masterfrom
feature/switch2kit-auto-connect

Conversation

@jmonster

@jmonster jmonster commented Sep 18, 2026

Copy link
Copy Markdown
Owner

Problem

A controller can power off during a long pause. Dolphin's 60-second native discovery window has already expired by the time it wakes, so the user must reopen Controller Settings and press Find. The input mapping is not the cause.

User-facing behavior

Add Automatically connect Switch 2 controllers, off by default, to Controller Settings. Enabling it starts continuous discovery now and remembers the choice for future launches. A supported advertising controller can reconnect after an arbitrarily long absence without reopening settings. The status distinguishes listening from a finite manual search.

  • The preference is stored in [Settings] AutoConnect in Switch2Kit.ini, preserving existing physical identities and every other section.
  • Saved consent starts support exactly once on the main run loop, after SDL initialization. No settings-window lifetime, emulation-resume hook, repeated Find calls, or polling-based restart is involved.
  • Disconnect stays authoritative for the current run. A deferred startup callback, input polling or settings refresh cannot undo it. Find or explicitly re-enabling the option resumes support; saved consent applies at the next app launch.
  • Disabling automatic discovery retains ready controllers. Reconnection never reapplies presets or changes custom bindings/port assignments.
  • Failed configuration reads/saves do not overwrite existing configuration or change the runtime preference. Failed policy/start actions remain visible rather than being erased by the next input pump.

Automatic mode admits available supported controllers, not arbitrary Bluetooth devices and not only a saved-device allowlist. It still requires controller wake/advertisement, initial pairing and Bluetooth permission. Continuous scanning uses radio resources, while preserving the SDK's serialized handshakes, capacity limits, duplicate filtering and bounded retry behavior.

Dependency and native-fixture correction

Companion: jmonster/Switch2Kit#71

Current Dolphin head: 30c86e60dea8c521c2bddd8f3140971c8684c9d6.

Pin Externals/Switch2Kit to a9d43b1f63d94f8844755a510bf6ecc876bc8c51, which exposes the existing automatic policy through the additive s2k_set_automatic_discovery C symbol. The documented and CI-enforced pins match. Merge the SDK change first; this branch is directly buildable against its pinned PR commit. No ABI struct layout or old consumer default changes.

The original SDK revision missed the new ControllerSource.setAutomaticDiscovery requirement in the separate native SDLTestSource fixture. That broke its SDL/emulator-host consumer builds. The updated SDK implements the fixture method and compiles that exact fixture in ordinary SwiftPM tests, with three additional lifecycle/input regressions. This Dolphin correction changes only the submodule, documentation and CI-enforced pin; application behavior and all CI gates remain unchanged.

Validation

Current-head CI: Native Switch2Kit run. Its wiring job passed, including controller UI formatting, integration/preset checks, the four automatic-connection wiring checks, mapping sanitizer regressions, and production host lifecycle/identity/automatic-policy sanitizer regressions.

Still pending at this update: SDK/real-SDL/motor qualification and both complete arm64/x86_64 application builds with bundle/launch checks. Those are not represented as passing based on the wiring job or a previous revision. All existing jobs remain enabled.

Previously completed local validation of the unchanged host implementation against SHA-verified files:

  • Execute the production host wrapper with Clang ASan/UBSan and GCC ASan/UBSan, C++20, warnings as errors. Existing lifecycle/identity/concurrency checks and automatic-policy, saved-consent, failed-save, failed-policy, one-shot-startup, stop-before-start and explicit-stop checks pass.
  • Four static UI/startup/disabled-guard/CI-wiring checks pass.
  • No per-poll file I/O, repeated start/configuration calls or timed-window renewal in automatic mode; existing IDs survive preference changes.
  • Whitespace checks pass.

The companion SDK reports its separate corrected-head validation on dolphin-emu#71. Passing its package tests is not a substitute for this application's native consumer and complete build results.

Hardware acceptance (not yet performed)

Play → pause → controller off for more than 60 seconds → resume → turn controller on, without opening settings. Verify input resumes with the same port/mapping; repeat several times. Also test Bluetooth off/on, reverse reconnect order with two controllers, disabling the option while connected, normal app restart with the saved choice, and explicit Disconnect remaining stopped.

Prepared with AI assistance. No merge or force-push is performed.

Keep the native discovery policy listening beyond the manual 60-second window. Persist AutoConnect separately from controller identities, initialize on the main run loop after SDL, and honor explicit Disconnect without polling-based restarts or mapping changes. Pin the matching C facade and add lifecycle, preference and UI wiring regressions.

AI-assisted implementation. Local production-host tests pass under Clang and GCC ASan/UBSan; physical macOS controller recovery still requires acceptance.

Copy link
Copy Markdown
Owner Author

Validation update on b0bc2332ba7c67467decf7cbfa4a8b04eef37b47:

Dolphin's wiring CI job passed, including controller UI formatting, all existing integration/preset checks, the four new auto-connect wiring checks, production mapping tests under sanitizers, and production host lifecycle/identity/auto-connect tests under sanitizers.

Run: https://github.com/jmonster/dolphin/actions/runs/35296316013

All nine published text-file blob hashes were checked against the locally tested files and match exactly; the submodule is the intended SDK head. Local Clang and GCC ASan/UBSan host runs also passed.

The pinned SDK head has additionally passed Swift 6 concurrency, macOS build and regressions, and SDL input regressions; its Linux debug/release package-test steps passed as well. Other SDK workflows are still queued/running.

Dolphin's full arm64/x86_64 macOS application and SDK integration jobs are still queued as of this check. This is not a full-build or hardware qualification claim. Both PRs remain open and unmerged.

Advance Externals/Switch2Kit to a9d43b1f63d94f8844755a510bf6ecc876bc8c51 and update the documentation and CI-enforced pin together. The SDK fixes SDLTestSource protocol conformance and compiles the native fixture in ordinary Swift tests. Preserve all application behavior and validation gates.
@jmonster
jmonster merged commit 141c8c2 into master Sep 18, 2026
4 checks passed
@jmonster
jmonster deleted the feature/switch2kit-auto-connect branch September 18, 2026 04:43
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