DualSense manual Bluetooth disconnect, 2026-09-14¶
Historical record. This preserves the source, tests and limitations recorded at the time; it is not current setup guidance. See the documentation index.
Report and evidence¶
The user reported that pressing Disconnect turned off a Bluetooth DualSense, but its controller entry remained in DS4Windows. Inspection and tests were hardware-free; the running application and controllers were not changed.
The September 13 log contains a natural read failure (1167) at 23:19:54 followed by successful controller removal. That is not the reported manual-disconnect failure. A later virtual-device removal at 23:21:38 is explicitly a profile transition, not physical controller removal. The log does not timestamp the manual button press, so it cannot establish the exact failing interleaving.
Reproduced cause and fix¶
Both the controller-row action and tray action called DisconnectBT() with its
default callRemoval: false. This relies on a later physical read failure to
publish Removal. DualSense's one-shot lifecycle retires output/command workers
and consumes pending removal before disconnecting the radio. A read failure
arriving afterward has no remaining lifecycle consumer to deliver Removal.
Both manual UI callers now explicitly pass callRemoval: true. This reuses
the existing retirement path: output workers stop before radio I/O; Removal
revokes presentation and queues exact-device service cleanup. The controller
list removes the exact device and unsubscribes. Delayed old notifications
cannot remove a replacement in the same slot.
The optional default and transport lifecycle were not rewritten. Input, haptics, audio, triggers, packet formats, Nintendo paths and reconnection policies have no new changes in this fix. Previously pending workspace changes were preserved. Mapping's separate special-action disconnect path was not changed by this manual-UI fix.
Validation¶
DualSenseManualDisconnectTestsinvokes the actual controller-row and tray handlers plus real DualSense workers. Only hardware write/finalize/radio boundaries are substituted. Both tests failed before the fix because removal was not requested, and both passed afterward.- Tests verify removal with no HID read-failure notification, one removal callback, output/command retirement before radio I/O, retention of another controller, and protection of a replacement occupying the reused slot.
- The targeted lifecycle/read-failure/controller-list run passed all 36 tests.
- Full Release/x64 suite: 5,698 passed, 11 hardware-gated tests skipped, 0 failed (5,709 total). The build retained six existing compiler warnings; no new compile errors were introduced.
- Independent read-only review checked cleanup ordering, callback locks, duplicate removal, and the hardware-free fixture.
git diff --checkpassed.
Evidence: isolated_results/dualsense-manual-disconnect-20260914/red.trx,
green-targeted.trx, and full.trx.
Boundaries¶
No live Bluetooth disconnect or installed-build replacement was performed. The production base radio routine's existing forced-success behavior remains unchanged; these tests establish software cleanup following its accepted disconnect contract, not the correctness of native radio return codes.
The compiled DS4Windows.dll SHA-256 is
885A5EA767C46CE3B5D80E494B3C87AB046FC8A5715D7F5FE4A41FA3BD24AC5F.
This is a workspace build, not a new public release or portable deployment.