Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ jobs:
"$env:GITHUB_WORKSPACE\cmake-build-ci\examples\$env:CMAKE_BUILD_CONFIG" `
"gamepad_adapter.exe"
}
$profiles = @("generic", "xone", "xseries", "ds4", "ds5", "switch")
$profiles = @("generic", "x360", "xone", "xseries", "ds4", "ds5", "switch")
foreach ($profile in $profiles) {
.\scripts\windows\test-installed-driver.ps1 `
-GamepadAdapterPath $gamepadAdapterPath `
Expand Down
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ types.

Consumers work with portable concepts such as runtimes, device profiles,
normalized gamepad state, output callbacks, and device nodes. Platform-specific
details such as Linux `uhid`/`uinput` or the Windows UMDF/VHF driver package stay
behind backend implementations.
details such as Linux `uhid`/`uinput`, Windows VHF, or the Windows Xbox 360 XUSB
companion stay behind backend implementations.

## 🎮 Capabilities

Expand All @@ -49,9 +49,10 @@ behind backend implementations.
through Linux `uhid`; Generic and Xbox 360 gamepads plus keyboard, mouse,
touchscreen, trackpad, and pen tablet devices through `uinput`. Xbox One and
Xbox Series fall back to `uinput` when `uhid` is unavailable.
- Windows gamepads, keyboards, and Raw Input-visible mice through a user-mode
UMDF2 control driver backed by Virtual HID Framework, with Win32 keyboard and
mouse fallbacks when the licensed driver path is unavailable.
- Windows gamepads, keyboards, and Raw Input-visible mice through user-mode
UMDF2 drivers. Xbox 360 uses a broker-owned XUSB software-device personality;
the other profiles use Virtual HID Framework. Win32 keyboard and mouse
fallbacks remain available when the licensed driver path is unavailable.
- Output callbacks for profile-specific feedback such as ordinary and trigger
rumble, RGB and player LEDs, adaptive triggers, and raw HID output reports
when available.
Expand Down Expand Up @@ -111,8 +112,9 @@ devices from the OS, or ship a Windows kernel-mode driver.

Linux and Windows provide virtual-device backends. Linux uses standard
user-space kernel interfaces. Windows remains user-mode: the C++ library talks
to a UMDF2 control driver, and the driver publishes HID gamepads, keyboards,
and mice through VHF.
to a broker and UMDF2 package. The package publishes Xbox 360 through XUSB and
VHF together, and publishes the other gamepads, keyboards, and mice through
VHF.
macOS currently provides a limited CoreGraphics synthetic-input backend for
keyboard and mouse only. It is not a virtual-HID backend and does not yet
support gamepads; native macOS virtual-HID gamepad support is planned.
Expand All @@ -125,6 +127,10 @@ same API where the backend exposes them.

- The published Windows driver installer is AMD64-only. Windows ARM64 release
packages require a different Microsoft driver-signing path.
- Xbox 360 support implements the undocumented XUSB wire contract used by the
inbox XInput stack. It must be regression-tested on each supported Windows
release; Microsoft does not provide a supported public virtual-XInput driver
API.

## 🔁 Alternatives

Expand Down
7 changes: 5 additions & 2 deletions docs/maintainer/store-review-validation.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,11 @@ C:\ProgramData\libvirtualhid\install-driver.log

## Scope Notes

The `x360` profile is not used for Store review. The Windows UMDF/VHF backend is
HID-only and intentionally does not emulate the Xbox 360 XUSB stack.
The default Store-review path still uses Xbox Series and does not exercise the
`x360` profile. The package also installs the separate Xbox 360 XUSB companion;
validate that path with `test-installed-driver.ps1 -GamepadProfile x360` and the
installed-driver `Xbox360PublishesXInputStateAndRumble` integration test before
claiming Xbox 360 compatibility for a release.

The reviewer-visible success signal is the installed `ROOT\LIBVIRTUALHID`
control device, the `\\.\LibVirtualHid` control path, the running
Expand Down
40 changes: 27 additions & 13 deletions docs/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,23 @@ Use capability queries for behavior such as:

The Windows backend keeps the normal C++ library buildable with MSVC and
MinGW/UCRT64. Gamepad creation, Raw Input-visible keyboard input, and Raw
Input-visible relative mouse input use a user-mode UMDF2 control driver and
Windows Virtual HID Framework. Keyboard text input, absolute mouse input, and
the keyboard and mouse fallbacks use Win32 APIs.
Input-visible relative mouse input use a user-mode UMDF2 package. Xbox 360 uses
a per-controller XUSB software device plus a correlated VHF child; other
profiles use the root control driver and Windows Virtual HID Framework.
Keyboard text input, absolute mouse input, and the keyboard and mouse fallbacks
use Win32 APIs.

The C++ library communicates with the driver through fixed-size protocol
structures and `DeviceIoControl`, not C++ STL types. This keeps the public API
compiler-neutral and preserves the boundary between the MinGW/MSVC client
library and the WDK/MSVC driver package.

When the driver is installed and licensed, the backend publishes HID gamepads,
keyboards, and mice that standard HID and Raw Input consumers can enumerate.
Gamepad consumers include SDL/HIDAPI, DirectInput,
Windows.Gaming.Input/GameInput, and browser Gamepad API clients. XInput is not
a direct target of the HID backend.
When the driver is installed and licensed, the backend publishes gamepads,
keyboards, and mice that standard Windows consumers can enumerate. Xbox 360 is
a direct XInput/XUSB target while retaining a HID/DirectInput view; the other
gamepads are descriptor-driven VHF devices. Consumers include XInput,
SDL/HIDAPI, DirectInput, Windows.Gaming.Input/GameInput, and browser Gamepad API
clients.

Driver-backed keyboard key transitions use a standard keyboard-page HID report
with modifier state and sixteen simultaneous non-modifier usages. Unicode text
Expand Down Expand Up @@ -77,6 +80,16 @@ mask and duration field, and reports the body motors as normalized
low/high-frequency rumble and the independent trigger motors as trigger-rumble
output.

Xbox 360 uses a broker-owned System-class software devnode with an explicit
container ID. Its dedicated UMDF2 companion publishes the XUSB interface used
by `xinput1_4.dll`, while its VHF child preserves the public
`0x045E:0x028E&IG_00` HID identity. Input state is delivered at native XInput
precision and `XInputSetState` feedback is normalized into the public two-motor
rumble callback. This is a private Windows implementation detail; the public C++
profile and API remain platform-neutral. Because Microsoft does not document
XUSB as a third-party virtual-driver API, this compatibility layer requires
release-by-release installed-driver regression testing.

The VHF driver answers the calibration, pairing, and firmware feature reports
used to initialize DualShock 4 and DualSense HIDAPI output. It also answers the
Switch Pro USB and subcommand initialization sequence and accepts the native
Expand All @@ -97,16 +110,17 @@ lets Windows HID consumers retrieve the current battery state for Xbox One,
Xbox Series, DualShock 4, DualSense, and Switch Pro instead of relying only on
the asynchronous input stream.

That HID report does not change the XInput battery classification of the VHF
device. On a Windows desktop where XInput enumerated the virtual Xbox
controller, `XInputGetBatteryInformation` returned `BATTERY_TYPE_DISCONNECTED`
and `BATTERY_LEVEL_EMPTY` even while its input was available through
That HID report does not change the XInput battery classification of the Xbox
One and Xbox Series VHF devices. On a Windows desktop where XInput enumerated
one of those virtual Xbox controllers, `XInputGetBatteryInformation` returned
`BATTERY_TYPE_DISCONNECTED` and `BATTERY_LEVEL_EMPTY` even while its input was available through
`XInputGetState`. Headless Windows CI did not expose an XInput slot for the same
device. Neither path exposes the remote battery through XInput. Consumers that
prefer XInput, including SDL's correlated Windows Xbox path and Windows Game
Bar, therefore do not receive the remote Xbox battery value. DualShock 4,
DualSense, and Switch Pro battery state is independently covered through SDL's
HID path.
HID path. The Xbox 360 XUSB personality reports the fixed wired-controller
battery state and does not accept remote battery input.

The current Steam client displays its controller battery indicator only when it
classifies the device as Bluetooth or wireless. Because VHF exposes a wired
Expand Down
Loading
Loading