diff --git a/DS4Windows/App.xaml.cs b/DS4Windows/App.xaml.cs
index dacfcfb5..7c88e336 100644
--- a/DS4Windows/App.xaml.cs
+++ b/DS4Windows/App.xaml.cs
@@ -582,7 +582,7 @@ bool Probe(int timeoutMilliseconds, out string lastProbeFailure)
{
if (!portable.InspectOwnedProcess(out bool running, out string failure) || !running)
throw new DS4Windows.PortableBrokerStartupException(failure ??
- "The portable VIIPER process stopped before it was ready. Check that USB/IP 0.9.7.7 is installed and available, then restart DS4Windows.");
+ "The portable VIIPER process stopped before it was ready. Check that USB/IP 0.9.8.1 is installed and available, then restart DS4Windows.");
return DS4Windows.ViiperSetupManager.ProbeServer(
DS4Windows.ViiperSetupManager.ApiHost,
diff --git a/DS4Windows/DS4Control/Viiper/ViiperOutDevice.cs b/DS4Windows/DS4Control/Viiper/ViiperOutDevice.cs
index 01294515..6c742435 100644
--- a/DS4Windows/DS4Control/Viiper/ViiperOutDevice.cs
+++ b/DS4Windows/DS4Control/Viiper/ViiperOutDevice.cs
@@ -11705,7 +11705,7 @@ internal static bool IsDs4WindowsOwnedLocalPort(
return false;
}
- // usbip-win2 0.9.7.7 has no attach-time serial override. Its
+ // The published usbip-win2 0.9.8.1 serial override is broken. Our
// safe ownership identity is the exact VIIPER-only localhost
// server port plus the remote bus/device tuple. If a newer port
// listing does expose a serial, reject every foreign token.
@@ -11791,12 +11791,24 @@ private static bool TryParseSerial(string block, out string serial)
continue;
}
+ // 0.9.8.1 prints "-> serial: value", including an empty value
+ // when no override is supplied. Keep the older quoted form
+ // for upgrade cleanup, and never treat a foreign plain value
+ // as an absent serial.
+ const string plainPrefix = "-> serial:";
+ if (line.StartsWith(plainPrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ serial = line.Substring(plainPrefix.Length).Trim();
+ return serial.Length > 0;
+ }
+
int openingQuote = line.IndexOf('\'');
int closingQuote = openingQuote >= 0 ?
line.IndexOf('\'', openingQuote + 1) : -1;
if (openingQuote < 0 || closingQuote <= openingQuote + 1)
{
- return false;
+ serial = line.Substring("-> serial".Length).Trim();
+ return serial.Length > 0 && serial != "''";
}
serial = line.Substring(openingQuote + 1,
diff --git a/DS4Windows/DS4Control/Viiper/ViiperSetupManager.cs b/DS4Windows/DS4Control/Viiper/ViiperSetupManager.cs
index 50946cd0..3720a0d2 100644
--- a/DS4Windows/DS4Control/Viiper/ViiperSetupManager.cs
+++ b/DS4Windows/DS4Control/Viiper/ViiperSetupManager.cs
@@ -106,8 +106,8 @@ public string DisplayText
if (!UsbipInstalled)
{
return string.IsNullOrWhiteSpace(UsbipVersion)
- ? "usbip-win2 0.9.7.7 is missing"
- : $"usbip-win2 {UsbipVersion} must be replaced with supported 0.9.7.7";
+ ? "usbip-win2 0.9.8.1 is missing"
+ : $"usbip-win2 {UsbipVersion} must be replaced with supported 0.9.8.1";
}
if (!UsbipExecutableSafe)
@@ -156,7 +156,7 @@ public static class ViiperSetupManager
{
public const string ApiHost = "127.0.0.1";
public const int ApiPort = 3242;
- internal static readonly Version RequiredUsbipVersion = new Version(0, 9, 7, 7);
+ internal static readonly Version RequiredUsbipVersion = new Version(0, 9, 8, 1);
private const string InstallerScriptName = "install-viiper-backend.ps1";
private const string InstallerHostArgument =
@@ -169,7 +169,7 @@ public static class ViiperSetupManager
BundledViiperName + ".sha256";
internal const string SupportedViiperSha256 =
"9392A49E619E1D9B7956EA4BEDAFD2E74CBF5065C011554E80F756D1524F892B";
- private const string BundledUsbipName = "USBip-0.9.7.7-x64.exe";
+ private const string BundledUsbipName = "USBip-0.9.8.1-x64.exe";
private const string BundledHidHideName =
"HidHide_1.5.230_x64.exe";
private const string BundledFakerInputName =
@@ -198,11 +198,13 @@ public static class ViiperSetupManager
private const string UsbipUdeServiceName = "usbip2_ude";
private const string UsbipFilterServiceName = "usbip2_filter";
internal const string SupportedUsbipUdeSha256 =
- "51DB440065393E588A6B2585508C50EB3E1510B7B06D9AFA6C5BDE583751EA7D";
+ "ABD4FC43DCE40E027E4ACC884CBFE92433E026206F6565C5EE5284A39441169A";
internal const string SupportedUsbipFilterSha256 =
- "C290299FF4D0F6A597DB5CE03E15B29A5349CDCE7C587EBFBD9ECAECA04F73ED";
+ "B93A5FC3C23D56F9B49634742374E32F269E53F764CAA2D5FCB43E3259F7ECED";
internal const string SupportedUsbipExecutableSha256 =
- "FC1660E3759D8AF4CEDE48DBE194285A5A1DE85CE6E3216724499AFD32BE92E8";
+ "817DA219FA153B4B37C3BC1AA8FCC63F33E046188C57CC3DD2C60A6EF0883C56";
+ internal const string SupportedUsbipLibrarySha256 =
+ "F123EF5D288B817A890CBE39A3C2D212B3D8B1765C691C8703CCB76C7337986C";
private static readonly object serverStartLock = new object();
private static readonly object foreignViiperProcessLock = new object();
private static readonly ViiperDependencyReadiness dependencyReadiness = new(() =>
@@ -281,7 +283,9 @@ private static ViiperPrerequisiteStatus GetStatusCore(bool tryStartServer, bool
Version usbipVersion = TryGetUsbipVersion(usbipPath);
bool usbipInstalled = IsSupportedUsbipVersion(usbipVersion);
bool usbipExecutableSafe = usbipInstalled &&
- FileHasSha256(usbipPath, SupportedUsbipExecutableSha256);
+ FileHasSha256(usbipPath, SupportedUsbipExecutableSha256) &&
+ FileHasSha256(Path.Combine(Path.GetDirectoryName(usbipPath),
+ "libusbip.dll"), SupportedUsbipLibrarySha256);
bool usbipRuntimeReady = false;
string usbipProbeMessage;
ViiperDependencyStatus dependencies = dependencyReadiness.Read(refreshDependencies || tryStartServer);
@@ -304,7 +308,7 @@ private static ViiperPrerequisiteStatus GetStatusCore(bool tryStartServer, bool
else
{
usbipProbeMessage = !usbipExecutableSafe && usbipInstalled
- ? "The installed usbip.exe does not match the bundled 0.9.7.7 executable."
+ ? "The installed usbip.exe or libusbip.dll does not match the bundled 0.9.8.1 package."
: !usbipDriverFilesSafe &&
usbipInstalled
? usbipDriverIntegrityMessage
@@ -2611,7 +2615,7 @@ private static (bool Safe, string Message)
}
return (true,
- "The registered usbip-win2 0.9.7.7 driver files match the " +
+ "The registered usbip-win2 0.9.8.1 driver files match the " +
"verified signed package.");
}
catch (Exception ex)
diff --git a/DS4Windows/DS4Forms/ViiperSetupProgress.xaml b/DS4Windows/DS4Forms/ViiperSetupProgress.xaml
index d77effaf..47002d5b 100644
--- a/DS4Windows/DS4Forms/ViiperSetupProgress.xaml
+++ b/DS4Windows/DS4Forms/ViiperSetupProgress.xaml
@@ -83,11 +83,11 @@
-
-
+
diff --git a/DS4Windows/DS4Forms/ViiperSetupPrompt.xaml.cs b/DS4Windows/DS4Forms/ViiperSetupPrompt.xaml.cs
index 25cb620f..47faf21c 100644
--- a/DS4Windows/DS4Forms/ViiperSetupPrompt.xaml.cs
+++ b/DS4Windows/DS4Forms/ViiperSetupPrompt.xaml.cs
@@ -66,9 +66,9 @@ public ViiperSetupPrompt(string currentStatus,
: "The installed VIIPER does not match this DS4Windows package.";
requirementsHeadingText.Text = "Verified update required";
requirementsText.Text = usbipReplacementRequired
- ? "• Install and verify bundled VIIPER 0.1.9-rc4.6.6\n" +
+ ? "• Install and verify bundled VIIPER backend\n" +
"• Safely remove the unsupported USB-IP package\n" +
- "• Restart, then finish installing USB-IP 0.9.7.7"
+ "• Restart, then finish installing USB-IP 0.9.8.1"
: "• Install the exact bundled VIIPER build\n" +
"• Keep your existing installation location\n" +
"• The unverified backend will not be started";
@@ -88,8 +88,8 @@ public ViiperSetupPrompt(string currentStatus,
summaryText.Text = currentStatus;
requirementsHeadingText.Text = "Required before DS4Windows can run";
requirementsText.Text =
- "• Install the bundled VIIPER 0.1.9-rc4.6.6 build\n" +
- "• Install and verify USB-IP 0.9.7.7\n" +
+ "• Install the bundled VIIPER backend build\n" +
+ "• Install and verify USB-IP 0.9.8.1\n" +
"• Start DS4Windows only after the runtime probe passes";
installButton.Content = "Install / Repair";
installPortableButton.Content = "Keep DS4Windows portable";
diff --git a/DS4Windows/DS4WinWPF.csproj b/DS4Windows/DS4WinWPF.csproj
index f7db86b5..8a1a5554 100644
--- a/DS4Windows/DS4WinWPF.csproj
+++ b/DS4Windows/DS4WinWPF.csproj
@@ -189,13 +189,13 @@
PreserveNewest
PreserveNewest
-
- extras\USBip-0.9.7.7-x64.exe
+
+ extras\USBip-0.9.8.1-x64.exe
PreserveNewest
PreserveNewest
-
- extras\USBip-0.9.7.7-LICENSE.txt
+
+ extras\USBip-0.9.8.1-LICENSE.txt
PreserveNewest
PreserveNewest
diff --git a/DS4Windows/PortableBrokerContext.cs b/DS4Windows/PortableBrokerContext.cs
index 08099238..68eb7699 100644
--- a/DS4Windows/PortableBrokerContext.cs
+++ b/DS4Windows/PortableBrokerContext.cs
@@ -66,7 +66,7 @@ internal static string DescribeReadinessFailure(string probeFailure)
}
}
return "Portable VIIPER did not become ready.\n\nReadiness check: " + detail +
- "\n\nInclude this check in your bug report. Use a complete extracted portable package and USB/IP 0.9.7.7. " +
+ "\n\nInclude this check in your bug report. Use a complete extracted portable package and USB/IP 0.9.8.1. " +
"Use Install / Repair VIIPER in Settings to retry without closing DS4Windows. If a conflicting broker cannot be identified or accessed, close it manually first. Your key and profiles were not replaced.";
}
diff --git a/DS4Windows/PortableBrokerStartupDiagnostics.cs b/DS4Windows/PortableBrokerStartupDiagnostics.cs
index e53664e4..eb3906c5 100644
--- a/DS4Windows/PortableBrokerStartupDiagnostics.cs
+++ b/DS4Windows/PortableBrokerStartupDiagnostics.cs
@@ -9,7 +9,7 @@ internal static string DescribeExit(int? code)
string reason = code switch
{
70 => "USB/IP could not be found or its version could not be checked.",
- 71 => "The installed USB/IP version does not match the required version (0.9.7.7).",
+ 71 => "The installed USB/IP version does not match the required version (0.9.8.1).",
72 => "The USB/IP startup check timed out before VIIPER could open its connection.",
73 => "The USB/IP driver did not pass its compatibility check.",
74 => "VIIPER could not open or create its local connection key.",
diff --git a/DS4WindowsTests/InstallerBackendIdentityTests.cs b/DS4WindowsTests/InstallerBackendIdentityTests.cs
new file mode 100644
index 00000000..f97f4d83
--- /dev/null
+++ b/DS4WindowsTests/InstallerBackendIdentityTests.cs
@@ -0,0 +1,46 @@
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Security.Cryptography;
+using System.Text.RegularExpressions;
+using DS4Windows;
+
+namespace DS4WindowsTests;
+
+[TestClass]
+public class InstallerBackendIdentityTests
+{
+ [TestMethod]
+ public void BootstrapperIdentityMatchesTheActualBundledBackend()
+ {
+ string binary = Path.Combine(Root(), "extras", ViiperSetupManager.BundledViiperName);
+ using var stream = File.OpenRead(binary);
+ string digest = Convert.ToHexString(SHA256.HashData(stream));
+ string probe = Read("installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs");
+ Assert.AreEqual(digest, StringValue(probe, "ExpectedViiperHash"));
+ Assert.AreEqual(digest, ViiperSetupManager.SupportedViiperSha256);
+ Assert.AreEqual(FileVersionInfo.GetVersionInfo(binary).ProductVersion,
+ StringValue(probe, "ExpectedViiperVersion"));
+ }
+
+ [TestMethod]
+ public void InfrastructureDetectionUsesTheSamePackageMarkerAtEveryBoundary()
+ {
+ string marker = $"VIIPER-{ViiperSetupManager.SupportedViiperReleaseTag.TrimStart('v')}+USBIP-{ViiperSetupManager.RequiredUsbipVersion}";
+ Assert.AreEqual(marker, StringValue(Read("installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs"), "ExpectedMarker"));
+ Assert.AreEqual(marker, StringValue(Read("installer/DS4Windows.SetupActions/Program.cs"), "InfrastructureVersion"));
+ Assert.AreEqual(marker, StringValue(Read("extras/install-viiper-backend.ps1"), "$script:InfrastructureVersion"));
+ StringAssert.Contains(Read("installer/DS4Windows.Bundle/Bundle.wxs"),
+ $"InfrastructureInstalled = "{marker}"");
+ }
+
+ private static string StringValue(string source, string name)
+ {
+ Match match = Regex.Match(source, Regex.Escape(name) + "\\s*=\\s*\"([^\"]+)\"");
+ Assert.IsTrue(match.Success, $"Missing package identity: {name}");
+ return match.Groups[1].Value;
+ }
+
+ private static string Read(string file) => File.ReadAllText(Path.Combine(Root(), file));
+ private static string Root([CallerFilePath] string source = "") =>
+ Path.GetFullPath(Path.Combine(Path.GetDirectoryName(source)!, ".."));
+}
diff --git a/DS4WindowsTests/ViiperSetupManagerTests.cs b/DS4WindowsTests/ViiperSetupManagerTests.cs
index 9ef548e2..3d4c63c5 100644
--- a/DS4WindowsTests/ViiperSetupManagerTests.cs
+++ b/DS4WindowsTests/ViiperSetupManagerTests.cs
@@ -64,8 +64,10 @@ public void UsbipVersionRequiresPinnedSafe0977()
Assert.IsFalse(ViiperSetupManager.IsSupportedUsbipVersion(null));
Assert.IsFalse(ViiperSetupManager.IsSupportedUsbipVersion(
new Version(0, 9, 7, 6)));
- Assert.IsTrue(ViiperSetupManager.IsSupportedUsbipVersion(
+ Assert.IsFalse(ViiperSetupManager.IsSupportedUsbipVersion(
new Version(0, 9, 7, 7)));
+ Assert.IsTrue(ViiperSetupManager.IsSupportedUsbipVersion(
+ new Version(0, 9, 8, 1)));
Assert.IsFalse(ViiperSetupManager.IsSupportedUsbipVersion(
new Version(0, 9, 7, 8)));
Assert.IsFalse(ViiperSetupManager.IsSupportedUsbipVersion(
@@ -346,7 +348,7 @@ public void UnsupportedUsbipVersionForcesGuidedRepair()
Assert.IsTrue(ViiperSetupManager.
RequiresVerifiedViiperUpdate(status));
- status.UsbipVersion = "0.9.7.7";
+ status.UsbipVersion = "0.9.8.1";
status.UsbipInstalled = true;
status.UsbipExecutableSafe = true;
status.UsbipDriverFilesSafe = true;
@@ -360,7 +362,7 @@ public void UnsafeUsbipRuntimeAndCitrixBypassPromptSuppression()
{
ViiperPrerequisiteStatus status = new ViiperPrerequisiteStatus
{
- UsbipVersion = "0.9.7.7",
+ UsbipVersion = "0.9.8.1",
UsbipInstalled = true,
UsbipExecutableSafe = true,
UsbipDriverFilesSafe = false,
diff --git a/DS4WindowsTests/ViiperUsbipPortManagerTests.cs b/DS4WindowsTests/ViiperUsbipPortManagerTests.cs
index a6dedb32..4516851c 100644
--- a/DS4WindowsTests/ViiperUsbipPortManagerTests.cs
+++ b/DS4WindowsTests/ViiperUsbipPortManagerTests.cs
@@ -7,6 +7,30 @@ namespace DS4WindowsTests
[TestClass]
public class ViiperUsbipPortManagerTests
{
+ [DataTestMethod]
+ [DataRow("", true)]
+ [DataRow("DS4W0123456789A", true)]
+ [DataRow("foreign", false)]
+ [DataRow("DS4WIN1234567", false)]
+ [DataRow("'foreign'", false)]
+ public void Usbip0981PortListingPreservesExactLocalOwnership(string serial, bool expected)
+ {
+ // Official 0.9.8.1 userspace/usbip/port.cpp output, including the
+ // new plain serial and receive-mode lines.
+ string output = "Imported USB devices\n====================\n" +
+ "Port 07: device in use at high-speed\n" +
+ " Sony Corp. DualSense\n" +
+ " -> usbip://localhost:3241/17-4\n" +
+ " -> remote bus/dev: 017/004\n" +
+ $" -> serial: {serial}\n" +
+ " -> mode: low-latency\n";
+ var ports = ViiperUsbipPortManager.ParseImportedPorts(output);
+ Assert.AreEqual(1, ports.Count);
+ Assert.AreEqual(7, ports[0].Port);
+ Assert.AreEqual(expected, ViiperUsbipPortManager.IsDs4WindowsOwnedLocalPort(ports[0], "17-4"));
+ Assert.IsFalse(ViiperUsbipPortManager.IsDs4WindowsOwnedLocalPort(ports[0], "17-5"));
+ }
+
[DataTestMethod]
[DataRow("localhost:3241/1-1", false)]
[DataRow("127.0.0.1:3241/1-1", false)]
diff --git a/docs/usbip-upgrade.md b/docs/usbip-upgrade.md
new file mode 100644
index 00000000..48e80596
--- /dev/null
+++ b/docs/usbip-upgrade.md
@@ -0,0 +1,21 @@
+# USB/IP 0.9.8.1 integration (draft)
+
+This contribution updates the required USB/IP version, vendor installer and
+file identities, userspace/driver ABI probes, serial parsing and the
+uninstall/restart/install boundary. It depends on the VIIPER 0.9.8.1 ABI port.
+
+## Required before merging or publishing
+
+The bundled VIIPER backend remains the existing upstream package while this
+change is reviewed. It must be replaced by the maintainer-approved build of
+the matching VIIPER contribution, with source/provenance/digest records updated
+as one package. The existing package must not be advertised as compatible
+with the new driver. CI packages from this draft are not a hardware-test release.
+
+Upstream release tags, signing policy, updater destinations and trusted
+repository identities are unchanged. No fork-produced VIIPER executable is
+substituted for the approved upstream dependency.
+
+Driver replacement still requires a user-controlled restart. Setup checks the
+matching usbip.exe, libusbip.dll and driver identities before enabling output.
+Port cleanup preserves the exact localhost endpoint and device ownership.
diff --git a/extras/USBip-0.9.7.7-LICENSE.txt b/extras/USBip-0.9.8.1-LICENSE.txt
similarity index 100%
rename from extras/USBip-0.9.7.7-LICENSE.txt
rename to extras/USBip-0.9.8.1-LICENSE.txt
diff --git a/extras/USBip-0.9.7.7-x64.exe b/extras/USBip-0.9.8.1-x64.exe
similarity index 63%
rename from extras/USBip-0.9.7.7-x64.exe
rename to extras/USBip-0.9.8.1-x64.exe
index 282b7332..e6cd9a6d 100644
Binary files a/extras/USBip-0.9.7.7-x64.exe and b/extras/USBip-0.9.8.1-x64.exe differ
diff --git a/extras/install-viiper-backend.ps1 b/extras/install-viiper-backend.ps1
index 679f2e7b..cacbcc2e 100644
--- a/extras/install-viiper-backend.ps1
+++ b/extras/install-viiper-backend.ps1
@@ -86,7 +86,7 @@ $script:UsbipReplacementPhaseOne = $false
$script:SetupMutex = $null
$script:SetupMutexOwned = $false
$script:SetupTransactionStarted = $false
-$script:RequiredUsbipVersion = [Version]"0.9.7.7"
+$script:RequiredUsbipVersion = [Version]"0.9.8.1"
$script:ViiperServerArguments =
"server --usb.retained-import-authority-id=4923336367393615921"
# RC4.5 / RC4.5.1-4 shipped this exact VIIPER executable. Their in-app
@@ -96,18 +96,20 @@ $script:ViiperServerArguments =
$script:LegacyPortableViiperSha256 =
"F1ECEF158F02D0BDCD1296C8D5097A281169081D0D59C1A8971592FAC78155EF"
$script:UsbipInstallerSha256 =
- "51620fa5f9f8be5932bc9d786deee557ce06d5407a99cab490dcfac71f185fea"
+ "38cad6d4432b52d5bb9409d9ad03b72fdffc4ada4cd3a48fbeca1a2752a8518a"
$script:UsbipExecutableSha256 =
- "fc1660e3759d8af4cede48dbe194285a5a1de85ce6e3216724499afd32be92e8"
+ "817da219fa153b4b37c3bc1aa8fcc63f33e046188c57cc3dd2c60a6ef0883c56"
+$script:UsbipLibrarySha256 =
+ "f123ef5d288b817a890cbe39a3c2d212b3d8b1765c691c8703ccb76c7337986c"
$script:UsbipUdeDriverSha256 =
- "51db440065393e588a6b2585508c50eb3e1510b7b06d9afa6c5bde583751ea7d"
+ "abd4fc43dce40e027e4acc884cbfe92433e026206f6565c5ee5284a39441169a"
$script:UsbipFilterDriverSha256 =
- "c290299ff4d0f6a597db5ce03e15b29a5349cdce7c587ebfbd9ecaeca04f73ed"
+ "b93a5fc3c23d56f9b49634742374e32f269e53f764caa2d5fcb43e3259f7eced"
$script:BundledViiperPath = Join-Path $script:PackageExtrasRoot `
"VIIPER-0.1.9-rc4.6.6-x64.exe"
$script:BundledViiperSha256Path = $script:BundledViiperPath + ".sha256"
$script:BundledUsbipInstallerPath = Join-Path $script:PackageExtrasRoot `
- "USBip-0.9.7.7-x64.exe"
+ "USBip-0.9.8.1-x64.exe"
$programFilesRoot = if ($env:ProgramW6432) {
$env:ProgramW6432
}
@@ -151,7 +153,7 @@ $script:UsbipReplacementStatePath = Join-Path $script:InstallDir `
$script:UsbipUninstallKeyName = `
"{199505b0-b93d-4521-a8c7-897818e0205a}_is1"
$script:InfrastructureRegistryPath = "HKLM:\SOFTWARE\DS4Windows"
-$script:InfrastructureVersion = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.7.7"
+$script:InfrastructureVersion = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.8.1"
$script:System32 = [Environment]::SystemDirectory
$script:PnPUtilPath = Join-Path $script:System32 "pnputil.exe"
$script:TaskKillPath = Join-Path $script:System32 "taskkill.exe"
@@ -551,7 +553,7 @@ function Get-UsbipDriverIntegrity {
}
if (-not [string]::Equals($hash, $expected[$serviceName],
[StringComparison]::OrdinalIgnoreCase)) {
- $details.Add("$serviceName does not match signed 0.9.7.7")
+ $details.Add("$serviceName does not match signed 0.9.8.1")
continue
}
@@ -668,7 +670,7 @@ function Resolve-UsbipReplacementBoundary {
$state.BootSessionId -eq $currentBootSessionId) {
$script:RebootBoundaryPending = $true
throw "USBIP replacement phase 1 is complete. Restart Windows before " +
- "running Install / Repair again; 0.9.7.7 was not installed."
+ "running Install / Repair again; 0.9.8.1 was not installed."
}
Write-SetupLog (
@@ -789,16 +791,17 @@ function Test-Ds4WindowsOwnedUsbipPort([string]$block) {
$serialLine = [regex]::Match(
$block, '(?im)^\s*->\s+serial\b(?.*)$')
if (-not $serialLine.Success) {
- # usbip-win2 0.9.7.7 cannot assign an attach-time owner serial. The
+ # The published 0.9.8.1 serial override is broken. The
# exact localhost VIIPER endpoint and bus/device tuple are its identity.
return $true
}
$serial = [regex]::Match(
- $serialLine.Groups['value'].Value, "^\s*'(?[^']*)'\s*$")
+ $serialLine.Groups['value'].Value,
+ "^\s*(?::\s*(?[^\r\n]*)|'(?[^']*)')\s*$")
if (-not $serial.Success) { return $false }
- $serialValue = $serial.Groups['serial'].Value
+ $serialValue = $serial.Groups['serial'].Value.Trim()
return [string]::IsNullOrEmpty($serialValue) -or
$serialValue -cmatch '^DS4W[0-9A-Fa-f]{11}$'
}
@@ -1112,11 +1115,13 @@ function Test-UsbipRuntime([string]$usbipPath) {
}
if (-not (Test-FileSha256 $usbipPath `
- $script:UsbipExecutableSha256)) {
+ $script:UsbipExecutableSha256) -or
+ -not (Test-FileSha256 (Join-Path (Split-Path -Parent $usbipPath) `
+ "libusbip.dll") $script:UsbipLibrarySha256)) {
$script:UsbipRuntimeProbeState = "executable-mismatch"
Write-SetupLog (
- "usbip.exe does not match the verified executable from the " +
- "bundled 0.9.7.7 package. Repair is required."
+ "usbip.exe or libusbip.dll does not match the verified files from the " +
+ "bundled 0.9.8.1 package. Repair is required."
) Yellow
return $false
}
@@ -1143,7 +1148,7 @@ function Test-UsbipRuntime([string]$usbipPath) {
if ($abiMismatch) {
$script:UsbipRuntimeProbeState = "abi-mismatch"
Write-SetupLog (
- "usbip-win2 0.9.7.7 is installed, but Windows still has a " +
+ "usbip-win2 0.9.8.1 is installed, but Windows still has a " +
"different driver ABI loaded. A reboot is required."
) Yellow
return $false
@@ -3097,7 +3102,7 @@ try {
Write-Host "Planned order:" -ForegroundColor Cyan
Write-Host " 1. Install VIIPER and register both elevated startup tasks." `
-ForegroundColor Cyan
- Write-Host " 2. Verify or install packaged usbip-win2 0.9.7.7." `
+ Write-Host " 2. Verify or install packaged usbip-win2 0.9.8.1." `
-ForegroundColor Cyan
Write-Host " 3. Verify the startup tasks remain exact and enabled." `
-ForegroundColor Cyan
@@ -3113,7 +3118,7 @@ try {
"interactively, or use -Yes after reviewing the installation " +
"and restart requirements."
}
- Write-Host "VIIPER is bundled and installs first. An incompatible USBIP driver is removed only after VIIPER is in place, and 0.9.7.7 is installed only after a separate reboot." -ForegroundColor Yellow
+ Write-Host "VIIPER is bundled and installs first. An incompatible USBIP driver is removed only after VIIPER is in place, and 0.9.8.1 is installed only after a separate reboot." -ForegroundColor Yellow
Write-Host "Save work before continuing; a driver replacement can require you to restart Windows and run Repair again." -ForegroundColor Yellow
$answer = Read-Host "Install bundled VIIPER first and continue? [Y/N]"
if ($answer -notmatch '^(?i:y|yes)$') {
@@ -3276,7 +3281,7 @@ try {
Save-StartupSetupIntent "RepairRequired"
Set-InfrastructureStartupFailClosed $viiperPath $script:Ds4WindowsRestartPath
- Write-Step "Step 2 of 4 - Checking usbip-win2 0.9.7.7"
+ Write-Step "Step 2 of 4 - Checking usbip-win2 0.9.8.1"
$requiredUsbipVersion = $script:RequiredUsbipVersion
try {
$usbipVersion = Get-UsbipInstalledVersion
@@ -3289,7 +3294,9 @@ try {
$canonicalUsbipPresent = Test-Path -LiteralPath $script:CanonicalUsbipPath
$usbipExecutableSafe = $canonicalUsbipPresent -and
(Test-FileSha256 $script:CanonicalUsbipPath `
- $script:UsbipExecutableSha256)
+ $script:UsbipExecutableSha256) -and
+ (Test-FileSha256 (Join-Path (Split-Path -Parent $script:CanonicalUsbipPath) `
+ "libusbip.dll") $script:UsbipLibrarySha256)
$usbipDriverIntegrity = Get-UsbipDriverIntegrity
if ($usbipDriverIntegrity.InstalledServiceCount -lt 0) {
throw "USBIP driver integrity inspection failed: " +
@@ -3404,7 +3411,7 @@ try {
}
else {
$usbipInstaller = Join-Path $script:TempDir `
- "USBip-0.9.7.7-x64.exe"
+ "USBip-0.9.8.1-x64.exe"
if (-not (Test-Path -LiteralPath `
$script:BundledUsbipInstallerPath -PathType Leaf)) {
$missingUsbipName = Split-Path -Leaf `
@@ -3413,7 +3420,7 @@ try {
"missing $missingUsbipName."
}
Write-SetupLog (
- "Using the bundled usbip-win2 0.9.7.7 installer."
+ "Using the bundled usbip-win2 0.9.8.1 installer."
) Green
Assert-FileSha256 $script:BundledUsbipInstallerPath `
$script:UsbipInstallerSha256
@@ -3440,7 +3447,9 @@ try {
$canonicalUsbipPresent = Test-Path -LiteralPath $script:CanonicalUsbipPath
$usbipExecutableSafe = $canonicalUsbipPresent -and
(Test-FileSha256 $script:CanonicalUsbipPath `
- $script:UsbipExecutableSha256)
+ $script:UsbipExecutableSha256) -and
+ (Test-FileSha256 (Join-Path (Split-Path -Parent $script:CanonicalUsbipPath) `
+ "libusbip.dll") $script:UsbipLibrarySha256)
$usbipDriverIntegrity = Get-UsbipDriverIntegrity
$usbipDriverFilesSafe = [bool]$usbipDriverIntegrity.Safe
$usbipVersionReady = $canonicalUsbipPresent -and $usbipVersion -and
@@ -3484,7 +3493,7 @@ try {
Write-Host ""
Write-SetupLog (
"VIIPER is installed and the old USBIP package removal was " +
- "started. Packaged 0.9.7.7 was not installed. Restart Windows, " +
+ "started. Packaged 0.9.8.1 was not installed. Restart Windows, " +
"then run Install / Repair again to complete phase 2."
) Yellow
}
diff --git a/installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs b/installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs
index 537ad8e7..17c7597d 100644
--- a/installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs
+++ b/installer/DS4Windows.Bootstrapper/InfrastructureProbe.cs
@@ -10,13 +10,14 @@ namespace DS4Windows.Bootstrapper
{
internal static class InfrastructureProbe
{
- private const string ExpectedMarker = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.7.7";
+ private const string ExpectedMarker = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.8.1";
private const string ExpectedViiperVersion = "0.1.9-rc4.6.6";
private const string ExpectedViiperHash = "9392A49E619E1D9B7956EA4BEDAFD2E74CBF5065C011554E80F756D1524F892B";
- private const string ExpectedUsbipVersion = "0.9.7.7";
- private const string ExpectedUsbipHash = "FC1660E3759D8AF4CEDE48DBE194285A5A1DE85CE6E3216724499AFD32BE92E8";
- private const string ExpectedUdeHash = "51DB440065393E588A6B2585508C50EB3E1510B7B06D9AFA6C5BDE583751EA7D";
- private const string ExpectedFilterHash = "C290299FF4D0F6A597DB5CE03E15B29A5349CDCE7C587EBFBD9ECAECA04F73ED";
+ private const string ExpectedUsbipVersion = "0.9.8.1";
+ private const string ExpectedUsbipHash = "817DA219FA153B4B37C3BC1AA8FCC63F33E046188C57CC3DD2C60A6EF0883C56";
+ private const string ExpectedUsbipLibraryHash = "F123EF5D288B817A890CBE39A3C2D212B3D8B1765C691C8703CCB76C7337986C";
+ private const string ExpectedUdeHash = "ABD4FC43DCE40E027E4ACC884CBFE92433E026206F6565C5EE5284A39441169A";
+ private const string ExpectedFilterHash = "B93A5FC3C23D56F9B49634742374E32F269E53F764CAA2D5FCB43E3259F7ECED";
internal static bool IsHealthy()
{
@@ -30,7 +31,8 @@ internal static bool IsHealthy()
if (!VersionMatches(viiper, ExpectedViiperVersion) ||
!HashMatches(viiper, ExpectedViiperHash) ||
!VersionMatches(usbip, ExpectedUsbipVersion) ||
- !HashMatches(usbip, ExpectedUsbipHash))
+ !HashMatches(usbip, ExpectedUsbipHash) ||
+ !HashMatches(Path.Combine(programFiles, "USBip", "libusbip.dll"), ExpectedUsbipLibraryHash))
{
return false;
}
diff --git a/installer/DS4Windows.Bootstrapper/InstallerWindow.xaml b/installer/DS4Windows.Bootstrapper/InstallerWindow.xaml
index 69072c45..9c74c6e7 100644
--- a/installer/DS4Windows.Bootstrapper/InstallerWindow.xaml
+++ b/installer/DS4Windows.Bootstrapper/InstallerWindow.xaml
@@ -105,8 +105,8 @@
-
-
+
+
diff --git a/installer/DS4Windows.Bundle/Bundle.wxs b/installer/DS4Windows.Bundle/Bundle.wxs
index dae0e06d..1cd32627 100644
--- a/installer/DS4Windows.Bundle/Bundle.wxs
+++ b/installer/DS4Windows.Bundle/Bundle.wxs
@@ -103,7 +103,7 @@
PerMachine="yes"
Permanent="yes"
Vital="yes"
- DetectCondition="InfrastructureInstalled = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.7.7" OR ManagedInstallRegistered OR ManagedViiperPresent"
+ DetectCondition="InfrastructureInstalled = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.8.1" OR ManagedInstallRegistered OR ManagedViiperPresent"
InstallArguments="install --correlation-id "[SetupCorrelationId]" --install-root "[ProgramFiles64Folder]DS4Windows" --bundle-id "[WixBundleProviderKey]" --desktop-shortcut "[CreateDesktopShortcut]" --target-user-sid "[TargetUserSid]" --target-user-name "[TargetUserName]" --target-local-appdata "[TargetLocalAppData]" --target-roaming-appdata "[TargetRoamingAppData]""
RepairArguments="repair --correlation-id "[SetupCorrelationId]" --install-root "[ProgramFiles64Folder]DS4Windows" --bundle-id "[WixBundleProviderKey]" --desktop-shortcut "[CreateDesktopShortcut]" --target-user-sid "[TargetUserSid]" --target-user-name "[TargetUserName]" --target-local-appdata "[TargetLocalAppData]" --target-roaming-appdata "[TargetRoamingAppData]""
UninstallArguments="uninstall --correlation-id "[SetupCorrelationId]" --install-root "[ProgramFiles64Folder]DS4Windows"">
diff --git a/installer/DS4Windows.SetupActions/Program.cs b/installer/DS4Windows.SetupActions/Program.cs
index dacbe08f..edc2d942 100644
--- a/installer/DS4Windows.SetupActions/Program.cs
+++ b/installer/DS4Windows.SetupActions/Program.cs
@@ -19,7 +19,7 @@ internal static class Program
{
private const string RegistryKeyPath = @"SOFTWARE\DS4Windows";
private const string InfrastructureVersion =
- "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.7.7";
+ "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.8.1";
private const string CurrentBundledViiperName =
"VIIPER-0.1.9-rc4.6.6-x64.exe";
private static string CorrelationId =
diff --git a/utils/post-build.py b/utils/post-build.py
index a037593b..86243456 100644
--- a/utils/post-build.py
+++ b/utils/post-build.py
@@ -78,7 +78,7 @@ def is_reparse_point(path: Path) -> bool:
"extras/VIIPER-SYSTRAY-NOTICE.md",
"extras/VIIPER-SYSTRAY-LICENSE.txt",
"extras/VIIPER-WDL-NOTICE.txt",
- "extras/USBip-0.9.7.7-x64.exe",
+ "extras/USBip-0.9.8.1-x64.exe",
"extras/HidHide_1.5.230_x64.exe",
"extras/FakerInput_0.1.0_x64.msi",
)
diff --git a/utils/test-localization-package.py b/utils/test-localization-package.py
index 5e7e7de1..ce64af6b 100644
--- a/utils/test-localization-package.py
+++ b/utils/test-localization-package.py
@@ -24,7 +24,7 @@
"extras/VIIPER-0.1.9-rc4.6.6-BUILD-NOTES.txt", "extras/LICENSE.txt",
"extras/VIIPER-SYSTRAY-NOTICE.md", "extras/VIIPER-SYSTRAY-LICENSE.txt",
"extras/VIIPER-WDL-NOTICE.txt",
- "extras/USBip-0.9.7.7-x64.exe", "extras/HidHide_1.5.230_x64.exe",
+ "extras/USBip-0.9.8.1-x64.exe", "extras/HidHide_1.5.230_x64.exe",
"extras/FakerInput_0.1.0_x64.msi",
)
SATELLITES = (
diff --git a/utils/test-viiper-reboot-boundary.ps1 b/utils/test-viiper-reboot-boundary.ps1
index fe6709ab..71820bab 100644
--- a/utils/test-viiper-reboot-boundary.ps1
+++ b/utils/test-viiper-reboot-boundary.ps1
@@ -53,11 +53,34 @@ foreach ($functionName in @(
"Set-UsbipReplacementBoundary",
"Remove-MismatchedUsbipPackage",
"Resolve-UsbipReplacementBoundary",
+ "Test-Ds4WindowsOwnedUsbipPort",
"Suspend-StartupTasksUntilInfrastructureReady",
"Set-InfrastructureStartupFailClosed")) {
Invoke-Expression (Get-BackendFunctionDefinition $functionName)
}
+# Parse the new upstream port output and the older quoted form without running
+# any installer top-level code or touching the installed USB/IP driver.
+foreach ($case in @(
+ @{ Line = '-> serial: '; Owned = $true },
+ @{ Line = '-> serial: DS4W0123456789A'; Owned = $true },
+ @{ Line = '-> serial: foreign'; Owned = $false },
+ @{ Line = "-> serial: 'foreign'"; Owned = $false },
+ @{ Line = "-> serial ''"; Owned = $true },
+ @{ Line = "-> serial 'DS4W0123456789A'"; Owned = $true },
+ @{ Line = "-> serial 'foreign'"; Owned = $false },
+ @{ Line = '-> serial foreign'; Owned = $false })) {
+ foreach ($location in @('localhost:3241/17-4', 'remote.example:3241/17-4',
+ 'localhost:3240/17-4', 'localhost:3241/x1-protected')) {
+ $block = "Port 07: device in use at high-speed`n -> usbip://$location`n $($case.Line)`n -> mode: low-latency"
+ $expected = $case.Owned -and $location -eq 'localhost:3241/17-4'
+ if ((Test-Ds4WindowsOwnedUsbipPort $block) -ne $expected) {
+ throw "USB-IP cleanup ownership mismatch: $location / $($case.Line)"
+ }
+ }
+}
+Write-Host "USB-IP cleanup rejects foreign imports in both port-output formats."
+
$testRoot = Join-Path ([IO.Path]::GetTempPath()) (
"DS4Windows-Usbip-Reboot-Test-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $testRoot | Out-Null
@@ -178,23 +201,23 @@ try {
}
$entry = [pscustomobject]@{
- DisplayVersion = "0.9.7.8"
+ DisplayVersion = "0.9.7.7"
QuietUninstallString = '"' + $uninstaller + '"'
UninstallString = $null
}
$removed = Remove-MismatchedUsbipPackage $entry `
- ([Version]"0.9.7.8") ([Version]"0.9.7.7")
+ ([Version]"0.9.7.7") ([Version]"0.9.8.1")
if (-not $removed -or -not $script:UsbipReplacementPhaseOne -or
-not $script:RebootRecommended -or
$script:UsbipRuntimeReady) {
- throw "0.9.7.8 phase-one replacement contract did not converge."
+ throw "0.9.7.7 phase-one replacement contract did not converge."
}
$state = Get-Content -LiteralPath $script:UsbipReplacementStatePath `
-Raw | ConvertFrom-Json
if ($state.BootSessionId -ne "boot-a" -or
- $state.RemovedVersion -ne "0.9.7.8" -or
- $state.RequiredVersion -ne "0.9.7.7") {
+ $state.RemovedVersion -ne "0.9.7.7" -or
+ $state.RequiredVersion -ne "0.9.8.1") {
throw "USB-IP replacement marker did not preserve exact versions."
}
@@ -251,7 +274,7 @@ try {
$failedUninstallRejected = $false
try {
[void](Remove-MismatchedUsbipPackage $entry `
- ([Version]"0.9.7.8") ([Version]"0.9.7.7"))
+ ([Version]"0.9.7.7") ([Version]"0.9.8.1"))
}
catch {
$failedUninstallRejected = $_.Exception.Message -match "exit code 5"
@@ -261,7 +284,7 @@ try {
throw "A failed USB-IP uninstall could authorize a later phase."
}
- Write-Host "USB-IP 0.9.7.8 -> reboot -> 0.9.7.7 state simulation passed."
+ Write-Host "USB-IP 0.9.7.7 -> reboot -> 0.9.8.1 state simulation passed."
}
finally {
Remove-Item -LiteralPath $testRoot -Recurse -Force `
diff --git a/utils/validate-installer.py b/utils/validate-installer.py
index 6f8893e6..0edf869a 100644
--- a/utils/validate-installer.py
+++ b/utils/validate-installer.py
@@ -29,7 +29,7 @@
"extras/VIIPER-SYSTRAY-NOTICE.md",
"extras/VIIPER-SYSTRAY-LICENSE.txt",
"extras/VIIPER-WDL-NOTICE.txt",
- "extras/USBip-0.9.7.7-x64.exe",
+ "extras/USBip-0.9.8.1-x64.exe",
"extras/HidHide_1.5.230_x64.exe",
"extras/FakerInput_0.1.0_x64.msi",
}
@@ -62,7 +62,7 @@
"VIIPER-SYSTRAY-LICENSE.txt": "05C55BD8834035C143C17AA218BFF08E22B7A66C5603CBA8F070DCAAFC974B8F",
"VIIPER-WDL-NOTICE.txt": "2485006947F464C2A69E9F863D50529261FB684A7AC5E6BAE0D03BFE65F9E025",
}
-VIIPER_INFRASTRUCTURE_MARKER = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.7.7"
+VIIPER_INFRASTRUCTURE_MARKER = "VIIPER-0.1.9-rc4.6.6+USBIP-0.9.8.1"
def parse_unique_provenance(source: str) -> dict[str, str]:
@@ -665,8 +665,8 @@ def main() -> int:
"Test-RecognizedProductExecutable",
'$script:InstallerLogRoot = Assert-SafeManagedDirectory',
'"VIIPER-0.1.9-rc4.6.6-x64.exe"',
- '[Version]"0.9.7.7"',
- '"USBip-0.9.7.7-x64.exe"',
+ '[Version]"0.9.8.1"',
+ '"USBip-0.9.8.1-x64.exe"',
'Start-AndVerifyViiper',
'Start-AndVerifyViiperDirectly',
'Suspend-StartupTasksUntilInfrastructureReady',