The driver installed but the device failed with Code 31 (CM_PROB_FAILED_ADD): VhfCreate returned STATUS_INVALID_DEVICE_REQUEST (0xC0000010) because vhf.sys was never attached beneath the FDO. Add the required LowerFilters=vhf AddReg to the INF so VHF loads as a lower filter; the device now starts clean and enumerates in joy.cpl. A VHF virtual HID device cannot supply a HID product string (VHF_CONFIG has no string field and VHF owns IOCTL_HID_GET_STRING), so register the DirectInput OEMName (VID_1209&PID_5249 -> RIOJoy Virtual Gamepad) in install.ps1 -CreateDevice and remove it in uninstall.ps1, giving the controller a proper name instead of the generic VHF default. Also fix a non-ASCII em-dash in sign.ps1 that broke parsing under Windows PowerShell 5.1 (UTF-8 without BOM), and document the Code 52 / Code 31 / friendly-name troubleshooting in driver/README.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
RIOJoy
Modern Windows 10/11 interface between the cockpit RIO (Remote Input/Output) board and Windows, as a virtual joystick / keyboard / mouse — the successor to the legacy vJoy-based app, with no vJoy dependency.
The RIO has 72 digital inputs and outputs (lighted buttons) and 5 analog axes (joystick X/Y, throttle, left pedal, right pedal), connected over RS-232 at 9600 8N1. RIOJoy exposes these to games that don't natively know about the cockpit hardware, with per-game profiles. (The native games — Firestorm, Red Planet — talk to the RIO directly and do not use this app.)
Repository layout
| Path | Contents |
|---|---|
src/RioJoy.Core |
Protocol, profile model, input mapper, HID feeder (class library) |
src/RioJoy.Tray |
Background tray application |
tests/RioJoy.Core.Tests |
xUnit tests for the protocol core |
driver/ |
RioGamepad virtual HID driver (KMDF + VHF) — replaces vJoy |
docs/PLAN.md |
Full modernization plan (7 phases) |
docs/PROTOCOL.md |
RIO wire format + iRIO input-map reference |
docs/reference/ |
Cockpit overlay art & the legacy labeling pipeline |
legacy/ |
Original C++/vJoy implementation, kept as reference |
Building
Requires the .NET 8 SDK and Windows. The driver builds separately with the
WDK (see driver/README.md).
dotnet build RioJoy.sln -c Release
dotnet test RioJoy.sln
Status
Phases 1–5 are implemented and tested (136 unit tests): the RioGamepad virtual
HID driver compiles to .sys against the EWDK (KMDF + VHF), and the C# side
covers the serial + RIO protocol core, input mapping + output routing, axis
calibration + plasma display, the tray app + profiles (JSON config, RIO.ini
importer, three-state auto-switch), and the HID report packer that matches the
driver's wire format. Remaining work is deploy-side: test-sign + install the
driver, wire the real DeviceIoControl feeder, and verify on a cabinet. See
docs/PLAN.md for the full roadmap.