Skip to content

About

Investigation archive: three DualShock 3 pads over Bluetooth on Windows Server 2019

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

License OS Status

DualShock 3 on Windows Server 2019 v1.0.0

Investigation Archive: Three DS3 Pads Over Bluetooth on a Server SKU

Version: 1.0.0
Release Date: July 27, 2026
OS: Windows Server 2019 Standard (10.0.17763)


Table of Contents


Overview

Getting three PlayStation 3 controllers working — wired and over Bluetooth, simultaneously, in a real game — on Windows Server 2019 Standard (10.0.17763), a SKU Microsoft never intended to run games on.

This is a private archive of a debugging session, not a software project. It exists so the setup can be rebuilt quickly if it breaks, and so the reasoning is preserved rather than re-derived.


Status

Working, and it survives a reboot. Three DS3 pads, all on Bluetooth, 10+ consecutive rounds of SpiderHeck, minimal latency; verified again after a full restart with no reconfiguration. One acceptance item genuinely fails — see Known Gaps.


The 60-Second Version

The problem was never one fault. It was five, four in software and one physical, which is why every earlier attempt that fixed one of them still failed.

# Fault Fix
1 DsHidMini in GPJ mode produces two HID collections per pad, so one pad appears as two controllers Mode to SXS
2 Default mode XInput, which requires xinputhid.sys — Windows Server ships no XInput HID stack at all Mode to SXS
3 HID mode stored per USB port instance (DsHidMini v2), so the same pad behaved differently per port Upgrade to v3, one machine-wide JSON
4 BthPS3\Parameters\IsSIXAXISSupported = 0, so the profile driver refused DS3 connections Set to 1
5 Bluetooth adapter rear-mounted behind a steel case, out of practical range USB extension cable, adapter moved to the front of the desk, line of sight

The single most important fact

C:\Windows\System32\drivers\xinputhid.sys   ->  ABSENT
C:\Windows\INF\xinputhid.inf                ->  ABSENT
C:\Windows\WinSxS  (xinputhid*)             ->  not staged anywhere on disk

Windows client SKUs ship xinputhid.sys; Windows Server does not, and it cannot be installed. DsHidMini's default XInput mode therefore produces a pad that presents a Microsoft VID (045E/02FF), which games and SDL deliberately exclude from HID/DirectInput enumeration on the assumption XInput will supply it — and nothing does.

That is the trap: the device node is healthy, Device Manager is spotless, and the game sees nothing. Switching to SXS mode restores the genuine Sony identity (054C/0268), which Steam Input already has a complete SDL mapping for.

Faults 4 and 5 look identical from inside the OS

Both produce: pad wakes, all four LEDs flash, powers off, nothing appears at any software layer.

There is no measurement inside Windows that distinguishes "the profile driver refused it" from "it never reached the radio". Both had to be fixed; neither alone was sufficient. If Bluetooth is misbehaving, check the antenna placement before debugging software — see docs/TROUBLESHOOTING.md §4, Cause 0.


Where to Start

If you want to Read
Rebuild this on a fresh machine docs/RUNBOOK.md — 10 phases, verification after each
Fix something that broke docs/TROUBLESHOOTING.md — symptom to cause to fix
Understand why it is built this way docs/ARCHITECTURE.md — design, rejected alternatives, limits
See the acceptance results docs/FINAL_REPORT.md — per-criterion pass/fail with evidence
Follow the reasoning step by step docs/WORKLOG.md — live hypothesis to change to observation to verdict, E0-E17
Undo something quarantine/…/MANIFEST.md — everything removed plus restore commands

Just make it work again: docs/RUNBOOK.md, top to bottom. Something regressed: docs/TROUBLESHOOTING.md fast-triage table. Prove or fix the hardware layer: the scripts in tools/.


The Working Configuration

        DualShock 3  x3
              |
      +-------+--------+
    USB             Bluetooth
      |                 |
      |      TP-Link UB500  <- ON A USB EXTENSION, FRONT OF DESK, LINE OF SIGHT
      |                 |
      |      BthPS3PSM  2.10.470.0   (Bluetooth class lower filter)
      |      BthPS3     2.10.470.0   (profile driver, IsSIXAXISSupported = 1)
      +-------+---------+
              |
      DsHidMini v3.3.1187.0  (UMDF, Microsoft WHQL-signed)
      mode = SXS   <- %ProgramData%\DsHidMini\DsHidMini.json
              |
      ONE HID collection per pad - VID_054C&PID_0268, Joystick, 13-byte reports
              |
      Steam Input  (SDL binding "PS3 Controller", keyed to 054C/0268)
              |
            game

Key settings, if you only remember three things:

# 1. HID mode  (a STRING, not a number - a number silently falls back to the default)
#    C:\ProgramData\DsHidMini\DsHidMini.json
{ "Global": { "HidDeviceMode": "SXS" }, "Devices": {} }

# 2. Bluetooth DS3 support
HKLM\SYSTEM\CurrentControlSet\Services\BthPS3\Parameters\IsSIXAXISSupported = 1  (DWORD)

# 3. The adapter must physically reach the players.

Tools

Written during the investigation because Windows Server 2019 doesn't ship equivalents, and because joy.cpl had already proven worthless as evidence here — a control panel showing clean input coexisted with a game receiving nothing.

Tool What it does Why it exists
PadProbe.exe / .cs Independent L1/L2 enumerator: real HID caps via HidP_GetCaps, real XInput slots Trust nothing that isn't measured directly. PadProbe json for diffing states
DevNode.exe / .cs Lists and removes PnP nodes including non-present ghosts Server 2019 has neither Remove-PnpDevice nor pnputil /remove-device
SET_MODE.ps1 Changes HID mode safely Encodes three silent-failure traps (see below)
VERIFY_AFTER_REBOOT.ps1 Automated post-reboot state check Kept for diagnosing a future regression — criterion 5 is already closed at L4
RUN_MATRIX_TEST.ps1 Full acceptance matrix, auto-captures evidence per cell Refuses to run over RDP
TEST_INGAME.ps1 Short focused in-game check Same RDP guard
CLEAN_GHOSTS.ps1 Tidies phantom device nodes Cosmetic only, and says so
AUDIT_REFERENCE_LAPTOP.ps1 Read-only audit of a known-good machine How the root cause was isolated

Rebuild the binaries from source at any time:

$csc = 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe'
& $csc /nologo /optimize+ /platform:x64 /out:PadProbe.exe PadProbe.cs
& $csc /nologo /optimize+ /platform:x64 /out:DevNode.exe  DevNode.cs

Three traps that cost real time

All three fail silently, with the driver falling back to defaults and reporting nothing:

  1. Config path has a subdirectory — %ProgramData%\DsHidMini\DsHidMini.json, not %ProgramData%\DsHidMini.json
  2. HidDeviceMode is a string — "SXS", not 3. A number makes cJSON_GetStringValue return NULL.
  3. The file ACL must grant LOCAL SERVICE — DsHidMini is UMDF and runs inside WUDFHost.exe as NT AUTHORITY\LOCAL SERVICE. Creating or moving the file can leave ACLs that exclude it.

SET_MODE.ps1 handles all three. Prefer it to hand-editing.


Repository Layout

+-- README.md                    <- you are here
+-- MASTER_PROMPT.md             the original brief this session was given
+-- LICENSE
|
+-- docs/                        the readable documents - start here
|   +-- RUNBOOK.md               bare metal -> working, 10 phases
|   +-- ARCHITECTURE.md          design rationale, rejected alternatives, limits
|   +-- TROUBLESHOOTING.md       symptom -> cause -> fix
|   +-- FINAL_REPORT.md          per-criterion verdict + honest self-assessment
|   +-- WORKLOG.md               full reasoning trail, E0-E17
|
+-- tools/                       scripts, source, and built binaries (see Tools above)
|   +-- PadProbe.cs / .exe       L1/L2 controller enumerator
|   +-- DevNode.cs / .exe        ghost-node listing + removal
|   +-- VigemProbe.cs / .exe     ViGEmBus virtual-target proof
|   +-- SET_MODE.ps1             safe HID-mode switching
|   +-- CLEAN_GHOSTS.ps1         tidy phantom device nodes
|   +-- RUN_MATRIX_TEST.ps1      full acceptance matrix (console only)
|   +-- TEST_INGAME.ps1          focused in-game check (console only)
|   +-- VERIFY_AFTER_REBOOT.ps1  post-reboot state check
|   +-- AUDIT_REFERENCE_LAPTOP.ps1  read-only known-good comparison
|
+-- evidence/                    timestamped results, from the physical console - never RDP
|   +-- MATRIX_RESULTS_20260727T013151Z.txt
|   +-- COLDBOOT_VERIFY_20260727T045152Z.txt
|   +-- reference_laptop_audit.txt
|   +-- reference_laptop_audit_with_ds3_connected.txt
|   +-- (run logs)
|
+-- quarantine/<UTC>/            NOTHING WAS DELETED - everything removed lives here
|   +-- MANIFEST.md              what, where from, why, exact restore command
|   +-- registry/                pre-change registry exports (10)
|   +-- removed_device_nodes/    13 phantom node exports
|   +-- certificates/            3 certs removed from machine trust stores
|   +-- driverstore_.../         the superseded DsHidMini v2.2.282.0 package
|
+-- installers/                  third-party installers, as downloaded (SHA-256 in WORKLOG)
    +-- Nefarius_DsHidMini_*.msi, Nefarius_BthPS3_*.msi, HidHide_*.exe, SteamSetup.exe, ViGEmBus_*.exe
    +-- dshm35_extract/          extracted DsHidMini payload
    +-- bthps3_extract/          extracted BthPS3 payload
    +-- vigem_extract/           extracted ViGEmBus payload (OS-gated installer workaround)
    +-- ds4w/                    DS4Windows fallback (staged, deliberately never installed)

Two upstream clones are gitignored (they contain their own .git, which does not archive cleanly). Re-clone if needed; the commits and tags that mattered are cited in WORKLOG.md:

git clone https://github.com/nefarius/DsHidMini.git _research/DsHidMini
git clone https://github.com/nefarius/ViGEmBus.git  ViGEmBus

installers/ (~95 MB of third-party binaries) is committed deliberately: the exact bytes that were installed, with hashes recorded. This is the only directory worth dropping if you ever want a lean copy — the download URLs and SHA-256 values in WORKLOG.md make it fully reproducible. The docs, tools, source and evidence total only ~15 MB.


Known Gaps

Stated plainly rather than rounded up.

Criterion Status
Wired playable PASS — but the success run was Bluetooth; wired L4 not separately re-tested in the final config
Wireless playable PASS — 3 pads, 10+ rounds
Replug idempotent PASS — verified across four different USB ports, always exactly one interface
N pads give N identities PASS
Cold-boot survival PASS — verified at L4: restarted, connected, launched, played, no reconfiguration
LED reflects player slot FAIL — genuinely fails. Not a bug — a plain HID gamepad has no slot concept, so the DS3 LED shows battery. Fixing it needs real XInput (DS4Windows + HidHide + ViGEmBus), which caps the machine at 4 pads and adds three components. That path is proven working here and fully staged — see ARCHITECTURE.md §5. Deliberately not deployed.

Notes for Future-You

  • Never test controllers over RDP. Gamepad enumeration, XInput visibility and input hooking all behave differently in a remote session. Both test harnesses refuse to run remotely by default. Detect it with GetSystemMetrics(0x1000).
  • Close Steam when diagnosing, run it when playing. It claims controllers and distorts measurements — but Steam Input is part of the working stack, not an accident.
  • On Windows 10/11 none of this is necessary. Client SKUs ship xinputhid.sys, so SET_MODE.ps1 XInput gives a real XInput device with real player slots and correct LEDs, with no ViGEm/DS4Windows/HidHide. The reference laptop runs the same DsHidMini driver and simply works. If this machine is ever rebuilt, a client SKU removes this entire problem class.
  • System Restore does not exist on Server 2019. Rollback here is registry exports, the preserved driver-store package, and the fact that removed device nodes are recreated on replug.
  • Bluetooth range is a configuration item. Moving the tower or re-seating the adapter can regress it with no software change and no software symptom.

Provenance

Investigated and documented in a single session using Claude Code, working from the brief preserved in MASTER_PROMPT.md. The software faults were found by measurement — device tree, INF contents, driver source, registry — and each fix was applied one variable at a time with the result recorded in WORKLOG.md.

The fifth fault — the Bluetooth adapter's physical placement — was found by the human operator, not by the tooling. No software instrumentation could have distinguished it from the driver-side fault it perfectly mimicked. That is written up honestly in FINAL_REPORT.md under Honest assessment, alongside a correction to a conclusion about Steam that turned out to be wrong.

Third-party components are the work of Nefarius Software Solutions (DsHidMini, BthPS3, ViGEmBus, HidHide) and are used under their own licences.


Author

Tchicdje Kouojip Joram Smith (DeltaGa)
Email: dev.github.tkjoramsmith@outlook.com
GitHub: https://github.com/DeltaGa


© 2026 DeltaGa. All rights reserved.

About

Investigation archive: three DualShock 3 pads over Bluetooth on Windows Server 2019

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages