Files
riojoy/driver/README.md
T
CydandClaude Opus 4.8 5dddbd2694 Phase 1 (3b): driver signing/install scripts + C# HID feeder sink
Make the virtual gamepad deployable on owned cabinets and wire the real
user-mode feeder:

- driver/sign.ps1 (non-admin): create a self-signed code-signing cert, build the
  catalog with inf2cat, and SHA-256-sign RioGamepad.sys + .cat (embed-sign the sys
  before cataloguing so the .cat matches). Exports RIOJoyTest.cer. Verified
  end-to-end against the EWDK (signability + catalog clean; both files signed).
- driver/install.ps1 (admin, two-phase): trust the cert (LocalMachine Root +
  TrustedPublisher), stage the package (pnputil /add-driver), enable test signing;
  after reboot, -CreateDevice runs devgen to create root\RioGamepad so PnP installs
  it. uninstall.ps1 reverses it.
- RioJoy.Core.Output.HidFeederJoystickSink: opens the driver by
  GUID_DEVINTERFACE_RIOGAMEPAD (SetupAPI), maintains a RioHidReport, and submits it
  via DeviceIoControl(IOCTL_RIO_SUBMIT_REPORT) on each axis/button/hat change.
  RioCoordinator now uses it when the driver is present and falls back to the no-op
  sink otherwise (status shows "[no joystick driver]").
- gitignore the signing outputs (driver/package/, *.cat); driver/README.md gets the
  full build → sign → install → joy.cpl workflow.

Remaining = the actual elevated install + reboot + joy.cpl verification on the
cabinet (admin steps), and on-hardware confirmation of the feeder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 21:17:04 -05:00

3.6 KiB

RioGamepad — virtual HID driver

The RioGamepad virtual HID device replaces the legacy vJoy dependency. It is a KMDF driver built on the Windows Virtual HID Framework (VHF, vhf.sys) that presents a single HID game controller to Windows matching the layout the old app drove through vJoy:

Report field Count Notes
Axes 6 X, Y, Z, Rx, Ry, Rz — 16-bit
Hat switch 1 4-direction POV with null state
Buttons 96 12 bytes of button bits

The C# tray app feeds input reports to the driver through a custom DeviceIoControl IOCTL on the driver's control device; the driver relays them to Windows via VhfReadReportSubmit.

Status

Phase 1 — implemented and compiling. The driver source under RioGamepad/ builds cleanly to RioGamepad.sys against the EWDK (KMDF 1.15 + VHF, x64). It is a thin VHF relay: it creates the virtual HID device from the report descriptor and, on each IOCTL_RIO_SUBMIT_REPORT, forwards the caller's 25-byte report to VhfReadReportSubmit. All report packing lives in the C# client (RioJoy.Core.Hid.RioHidReport, unit-tested) so the wire format is pinned on both sides (RioGamepad/Public.h).

Not yet done: test-signing + install + verify in joy.cpl (the on-cabinet step), and wiring the real DeviceIoControl feeder sink (replacing the C# side's NullJoystickSink).

Building

With the EWDK mounted (e.g. drive E:), from this folder:

RioGamepad\build.cmd E:

This sources the EWDK env (<EWDK>\BuildEnv\SetupBuildEnv.cmd) and runs MSBuild, producing RioGamepad\x64\Release\RioGamepad.sys. The project is a WDK/MSBuild .vcxproj; it is not part of RioJoy.sln (different toolchain).

EWDK note: the build disables the managed catalog task (/p:DriverCatalog_Enable=false) and auto-signing (/p:SignMode=Off). On this EWDK image the in-build DrvCat task can't load Microsoft.Kits.Logger, so the .cat is produced separately with inf2cat.exe and signed with signtool.exe as part of install (below), rather than during compilation.

Test-signing & install (cabinets you own)

Scripts in this folder automate the test-signing flow. Steps marked (admin) need an elevated shell; everything else is non-admin.

:: 1. Build the driver (non-admin), EWDK mounted at E:
RioGamepad\build.cmd E:

:: 2. Test-sign: makes a self-signed cert, builds + signs the .cat and .sys,
::    and exports RIOJoyTest.cer  (non-admin)
powershell -ExecutionPolicy Bypass -File sign.ps1 -Ewdk E:

:: 3. (admin) Trust the cert, stage the driver, enable test signing
powershell -ExecutionPolicy Bypass -File install.ps1 -Ewdk E:

:: 4. REBOOT  (test signing only takes effect after a restart)

:: 5. (admin) Create the device; PnP then installs the staged driver
powershell -ExecutionPolicy Bypass -File install.ps1 -Ewdk E: -CreateDevice

Then open joy.cpl and confirm "RIOJoy Virtual Gamepad" appears with 6 axes / POV / 96 buttons. To roll back: uninstall.ps1 [-DisableTestSigning] [-RemoveCert].

The signed package (package/) and the exported cert are local artifacts and are git-ignored. Redistribution beyond owned hardware would instead use Microsoft attestation signing via Partner Center (see ../docs/PLAN.md, Phase 6).

The user-mode side opens this device by GUID_DEVINTERFACE_RIOGAMEPAD and feeds reports via IOCTL_RIO_SUBMIT_REPORT — implemented by RioJoy.Core.Output.HidFeederJoystickSink, which the tray app uses automatically when the driver is present (falling back to a no-op sink when it is not).