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>
91 lines
3.8 KiB
PowerShell
91 lines
3.8 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Trust the test cert, enable test signing, stage and install the RioGamepad
|
|
driver. REQUIRES AN ELEVATED (admin) shell.
|
|
|
|
.DESCRIPTION
|
|
Two phases, because enabling test signing needs a reboot:
|
|
|
|
install.ps1 (phase 1, pre-reboot)
|
|
- import RIOJoyTest.cer into LocalMachine Root + TrustedPublisher
|
|
- stage the signed package into the driver store (pnputil /add-driver)
|
|
- bcdedit /set testsigning on
|
|
- THEN REBOOT
|
|
|
|
install.ps1 -CreateDevice (phase 2, after the reboot)
|
|
- create the root-enumerated device with devgen, which makes PnP install
|
|
the staged driver. Then check joy.cpl.
|
|
|
|
Run driver\sign.ps1 first to produce the signed package + RIOJoyTest.cer.
|
|
|
|
.PARAMETER Ewdk
|
|
Drive or root where the EWDK is mounted (default: E:).
|
|
.PARAMETER CreateDevice
|
|
Run phase 2 (create the device); use after the reboot.
|
|
#>
|
|
param(
|
|
[string]$Ewdk = "E:",
|
|
[switch]$CreateDevice
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$scriptDir = $PSScriptRoot
|
|
$pkg = Join-Path $scriptDir "package"
|
|
$inf = Join-Path $pkg "RioGamepad.inf"
|
|
$cer = Join-Path $scriptDir "RIOJoyTest.cer"
|
|
$devgen = Join-Path $Ewdk "Program Files\Windows Kits\10\Tools\10.0.28000.0\x64\devgen.exe"
|
|
$hardwareId = "root\RioGamepad"
|
|
|
|
# DirectInput / joy.cpl friendly name. 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 without this the controller shows as the generic
|
|
# "Virtual HID Framework (VHF) HID device". DirectInput reads the display name
|
|
# from this OEMName value, keyed by VID/PID (see RioGamepad\Public.h:
|
|
# RIO_VENDOR_ID 0x1209 / RIO_PRODUCT_ID 0x5249).
|
|
$oemVidPid = "VID_1209&PID_5249"
|
|
$friendlyName = "RIOJoy Virtual Gamepad"
|
|
|
|
function Set-RioJoyFriendlyName {
|
|
# Write the OEMName under both HKLM (machine-wide, authoritative) and HKCU
|
|
# (immediate effect for the current user) so joy.cpl shows $friendlyName.
|
|
$rel = "SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM\$oemVidPid"
|
|
foreach ($hive in @("HKLM:", "HKCU:")) {
|
|
$key = "$hive\$rel"
|
|
New-Item -Path $key -Force | Out-Null
|
|
New-ItemProperty -Path $key -Name "OEMName" -Value $friendlyName -PropertyType String -Force | Out-Null
|
|
}
|
|
Write-Host "Set joy.cpl friendly name for $oemVidPid -> '$friendlyName'."
|
|
}
|
|
|
|
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole(
|
|
[Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
throw "This script must be run from an elevated (Administrator) shell."
|
|
}
|
|
|
|
if ($CreateDevice) {
|
|
if (-not (Test-Path $devgen)) { throw "devgen not found: $devgen" }
|
|
Write-Host "Creating device node ($hardwareId)..."
|
|
& $devgen /add /instanceid "RIOJOY01" /hardwareid $hardwareId
|
|
Set-RioJoyFriendlyName
|
|
Write-Host ""
|
|
Write-Host "Done. Open 'joy.cpl' and look for 'RIOJoy Virtual Gamepad'." -ForegroundColor Green
|
|
Write-Host "If it shows a problem, check Device Manager and 'pnputil /enum-drivers'."
|
|
return
|
|
}
|
|
|
|
if (-not (Test-Path $inf)) { throw "Signed package not found ($inf). Run driver\sign.ps1 first." }
|
|
if (-not (Test-Path $cer)) { throw "Certificate not found ($cer). Run driver\sign.ps1 first." }
|
|
|
|
Write-Host "Trusting test certificate (LocalMachine Root + TrustedPublisher)..."
|
|
Import-Certificate -FilePath $cer -CertStoreLocation Cert:\LocalMachine\Root | Out-Null
|
|
Import-Certificate -FilePath $cer -CertStoreLocation Cert:\LocalMachine\TrustedPublisher | Out-Null
|
|
|
|
Write-Host "Staging driver into the driver store..."
|
|
pnputil /add-driver $inf
|
|
|
|
Write-Host "Enabling test signing..."
|
|
bcdedit /set testsigning on | Out-Null
|
|
|
|
Write-Host ""
|
|
Write-Host "Phase 1 complete. REBOOT, then run: install.ps1 -CreateDevice" -ForegroundColor Yellow
|