Skip to content

[Draft/RFC] Add experimental Native Mode for Bluetooth DualSense - #19

Draft
potpiemuncher wants to merge 12 commits into
ds4windowsapp:mainfrom
potpiemuncher:feature/native-dualsense-mode-upstream-pr
Draft

[Draft/RFC] Add experimental Native Mode for Bluetooth DualSense#19
potpiemuncher wants to merge 12 commits into
ds4windowsapp:mainfrom
potpiemuncher:feature/native-dualsense-mode-upstream-pr

Conversation

@potpiemuncher

@potpiemuncher potpiemuncher commented Jul 22, 2026

Copy link
Copy Markdown

[!CAUTION]> Architecture-review draft only - do not merge or distribute as an end-user feature.>> This PR is stacked on #18. Until #18 lands, the GitHub diff also contains> that PR's Bluetooth audio/haptics commits. Native Mode begins at 5391845,> directly after #18's current head 43c22fb; this branch will be rebased once> #18 is resolved.## SummaryNative Mode lets a game enumerate a virtual wired DualSense while the exactselected physical controller remains connected over Bluetooth. DS4Windowsreleases that pad, starts a loopback-only .NET 8 USB/IP helper, performs aper-use elevated attach, and relays:- controls and input reports;- adaptive-trigger and other HID output;- native four-channel haptic audio; and- game speaker audio back to the controller.The virtual microphone currently enumerates but returns silence. This work isseparate from #18's standard Bluetooth audio/haptics mode. That standard featureuses the real controller directly, needs no virtual USB hardware or third-partykernel driver, has been user-validated, and is not blocked by the Native Modegates below.## Safety status and production blockersNo usbip-win2 binary or driver is bundled. The tested Microsoft-attestation-signed usbip-win2 0.9.7.8 packages contain a confirmed request-lifetime race inusbip2_ude.sys: an audio-endpoint purge can overlap successful ISO completions.That path produced the captured BSODs during endpoint-close and Alt-Tab testing.This branch adds strict ISO generation quiescing, redundant parent/helper renderleases, cooperative parent-death shutdown, and fail-closed removal guards.Those mitigations reduced the reproduced trigger and survived controlled use,but they do not repair or prove the third-party kernel driver safe.Production use remains blocked until:- a signed usbip-win2 release fixes the lifetime defect, or maintainers choose another driver strategy;- redundant containment passes approved live parent/helper failure drills and stale-session reconciliation is implemented;- driver package version/signature validation plus install, repair, and uninstall policy are implemented and accepted; and- the captured Sony descriptor assets receive maintainer/provenance approval.The UI labels Native Mode experimental, presents the known BSOD risk, andrequires confirmation before every Start.## Startup and lifecycle hardening- Protocol v2 redirects the helper's standard input. stop requests normal cooperative shutdown; pipe EOF reports parent death.- NativeModeControlLease now starts its Console.In read on a dedicated long-running worker. The previous direct async call could block synchronously inside the synchronized console reader, preventing the USB/IP listener from starting until DS4Windows timed out and wrote stop.- The helper checks a completed stop/EOF lease before starting its child render baseline and again before advertising the server.- DS4Windows and the helper independently hold silent shared-mode render leases on the exact virtual endpoint. Attached is not published until both are healthy.- The helper stops accepting new connections before shutdown. Import reservation is atomic with that transition, and a successful import reply remains safety-relevant even before Windows materializes the PnP parent.- Active USB/IP and ISO request pumps are canceled and awaited while a healthy render lease remains. The helper releases its lease only after the tracked endpoint and fixed virtual parent are absent.- Attached-session Process.Kill was removed. A failed or timed-out stop leaves helper protections active and reports incomplete cleanup.- Startup blocks a second attach when the exact virtual parent is present or the presence probe cannot prove absence.- If a UAC decision outlives timeout or cancellation, the command becomes a fail-closed lifetime barrier: helper, render, and default-audio protections remain until the client exits and exact-device removal is rechecked.- Stopped plus retained protections is shown as cleanup pending with Stop still available; the UI changes to Start only after confirmed release.## Speaker-audio observability and game orderThe periodic ISO snapshot is now retained in the application log. It exposesonly transport counters and four-channel levels, with no controller identifieror device path. Channels 1/2 distinguish speaker audio from channels 3/4haptics, while bt-audio and bt-errors distinguish source silence from relayfailure.The controlled validation established that Auto routing was not the fault:the cleanly saved configuration remained Auto, and the same session producedaudible controller-speaker audio. The earlier silent case had haptics onchannels 3/4 but no speaker data on channels 1/2. After attaching Native Modebefore restarting the game, channels 1/2 became active and Bluetooth audioreports advanced with zero write errors. The UI and developer documentation nowtell users to wait for Attached before launching or restarting the game becausesome games retain the audio topology enumerated at process start.## Other hardening- The helper binds only to loopback and accepts only the selected controller's exact HID identity, VID/PID, transport, and Bluetooth report shape.- Managed serve is protocol-gated and fixed to Bluetooth input plus the composite topology.- usbip.exe must resolve canonically to that exact filename beneath Program Files or Program Files (x86).- Attach uses one direct UAC prompt with fixed loopback, bus, and virtual-serial arguments. No reusable privileged attach task is created or run.- Release builds publish the correct helper RID into native/, include only the six descriptor assets, and exclude debug/research output.## Validation- Native Mode-focused Release x64 tests: 175 passed, 0 failed.- Focused telemetry and status tests: 35 passed, 0 failed.- Standard Bluetooth haptics regression tests: 32 passed, 0 failed.- Packaged containment lifecycle self-test: 35 checks passed.- USB/IP codec and live-server self-tests passed, including descriptor/EP0, HID/audio/ISO/UNLINK, generation quiescing, watchdog, and import-stop races.- Fresh Release x64 and x86 app/helper package builds completed with 0 errors and only the documented warning baseline.- Full DS4Windows suite: 218 passed, 3 failed, 221 total. The failures are the pre-existing stale XML snapshots CheckSettingsSave, CheckJaysProfileRead, and CheckWriteProfile.- The post-containment controlled hardware session reached Attached without the earlier false timeout. Native controls, haptics, and controller speaker audio at 50 percent worked with the Auto route; speaker relay reached 1,364 audio reports with zero Bluetooth write errors. Normal shutdown confirmed virtual endpoint/device removal before releasing the render keepalive, and DS4Windows then exited cleanly.Repeated Alt-Tab stability was validated on the earlier stabilized build. Liveparent/helper hard-kill and stale-session recovery drills remain deliberatelyunperformed, so the production blockers above remain open.## Design and review dossiers- Native Mode architecture and blocker list- Parent/helper crash containment and failure matrix- Driver risk, validation, repair, and uninstall policy- Descriptor inventory, hashes, capture chain, and policy questionsThe crash dumps and full debugger logs remain private and are not part of thisrepository.## Dependencies and provenance- DS4Windows/helper code remains GPL-3.0-or-later; helper sources carry SPDX identifiers.- HidSharp 2.1.0 is Apache-2.0.- usbip-win2 0.9.7.8 is BSD-2-Clause and remains an external prerequisite.- Concentus, NAudio, DS5Dongle, and SAxense acknowledgements from #18 remain in THIRD-PARTY-NOTICES.txt.- The six byte-exact descriptor assets contain no USB serial, Bluetooth address, username, capture path, or gameplay data. The provenance dossier records their verified hashes and remaining Sony VID/PID/string policy decisions.## Requested reviewI am asking for maintainer feedback on the virtual-device/driver strategy,single-process failure containment, elevation boundary, driver-package policy,descriptor policy, and packaging approach. This draft should remainunmergeable until the production blockers above are closed.

potpiemuncher-alt and others added 9 commits July 20, 2026 21:55
Implements the policy §4 validation model: before DS4Windows releases the
physical controller or requests elevation to attach, the usbip-win2 driver
packages and the usbip.exe client must match a supported release-manifest
entry. Fails closed with a specific, non-sensitive diagnostic.

- NativeModeDriverManifest: single versioned data structure owning all
  tier/version/arch/signer policy. One ExperimentalBaseline entry for the
  tested 0.9.7.8 release (UDE 1.45.29.368, filter 1.45.28.868, usbip.exe
  ProductVersion 0.9.7.8, x64+x86, Microsoft Hardware Compatibility
  Publisher). A future fixed release can be added as a Production-tier entry
  without scattering version comparisons.
- NativeModeDriverValidation: IDriverPackageInspector / IAuthenticodeVerifier
  seams plus the pure, unit-testable manifest-matching and fail-closed
  decision logic (NativeModeDriverValidator), result type, and the
  NativeModeDriverGate wiring point.
- NativeModeDriverInspectors: OS-touching implementations. SetupAPI/CfgMgr32
  enumeration of the UDE host controller by the stable hardware ID
  ROOT\USBIP_WIN2\UDE (never a machine-specific instance), driver-store
  resolution of INF/provider/DriverVer/catalog/arch/health, and
  WinVerifyTrust (GENERIC_VERIFY_V2) trust with chain-derived signer
  identification of the Microsoft HWCP (no substring match).
- Wiring: ControlService.StartNativeModeAsync gates before controller release;
  NativeModeElevationBroker.RunAttachAsync re-validates before any elevation.
  0.9.7.8 is allowed as ExperimentalBaseline; unknown/older/newer/mixed/
  wrong-provider/test-signed/developer-signed/revoked/missing sets are refused.
- 33 offline MSTest cases covering policy §7.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The driver validation gate added in 180dbdb has OS-touching paths (SetupAPI
and Configuration Manager enumeration, driver-store INF resolution, and
WinVerifyTrust chain inspection) that no offline test can exercise, because
they require usbip-win2 to be installed. A mistake in any of them would fail
closed against a valid installation and block Native Mode with no way for a
user to tell whether their driver or the check itself was at fault.

Add a read-only `validatedriver` command that runs the same gate and reports
every value it observed next to the value the manifest expected, for all
three components, so a mismatch names itself. The report includes the signer
common name actually found on the verified chain, which is the value most
likely to be wrong and the hardest to guess offline.

The command runs from CheckOptions before the control service or main window
is created, requests no elevation, releases no controller, starts no helper,
and writes no settings. It attaches to a parent console when launched from a
terminal and otherwise shows the same text in a copyable window, always
writing the report to a file so it can be pasted into a bug report. Exit code
is 0 on pass and non-zero on failure so it can be scripted.

Report composition is a pure formatter covered by offline tests with
fabricated observations, including redaction of user paths.
CopyNativeDualSenseServer runs AfterTargets=Build and copies the published
helper into $(TargetDir)native. Release packaging uses `dotnet publish`,
whose output is assembled from publish item groups rather than from the build
output directory, so nothing carried the helper into a published package.

A published build therefore omitted native\VirtualDualSenseUsbip.exe, and
Native Mode failed at runtime when it could not locate the server executable.
The existing guard only proved the helper had been produced, not that it
shipped.

Register the helper files as ResolvedFileToPublish under native\ so publish
output matches build output. Verified with a clean CI-equivalent publish.
Record that the driver policy note's section 4 validation model is now
implemented rather than proposed, and describe what the gate enforces: stable
hardware-ID lookup, both packages matched against one release entry, trust
verified through the Windows trust APIs with the publisher taken from the
verified chain, and version and health checks, all fail-closed before the
controller is released or elevation is requested.

State the two limits plainly. Admitting release 0.9.7.8 as an experimental
baseline does not assert that release is safe, because the kernel lifetime
defect is unrepaired. And the enumeration and trust paths cannot be covered
offline, so validatedriver should be run on a real installation before any
build relying on this gate is distributed.

Update the blocker list to record that the upstream driver report has been
filed, that filing does not close the gate, and that the report cross-
references an independent case showing the same corruption signature with a
non-audio trigger. Install, repair, and uninstall policy remains open.
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