mirror of
https://github.com/dorssel/usbipd-win.git
synced 2026-11-10 14:43:56 +08:00
88 lines
3.2 KiB
C#
88 lines
3.2 KiB
C#
// SPDX-FileCopyrightText: 2020 Frans van Dorsselaer
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
using System.ComponentModel;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.ServiceProcess;
|
|
using static Usbipd.Interop.VBoxUsb;
|
|
using static Usbipd.Interop.VBoxUsbMon;
|
|
using static Usbipd.Tools;
|
|
|
|
namespace Usbipd;
|
|
|
|
sealed partial class VBoxUsbMon : IDisposable
|
|
{
|
|
readonly DeviceFile UsbMonitor = new(USBMON_DEVICE_NAME);
|
|
|
|
public static UsbSupVersion? GetRunningVersion()
|
|
{
|
|
try
|
|
{
|
|
using var mon = new VBoxUsbMon();
|
|
return mon.GetVersion().Result;
|
|
}
|
|
catch (Win32Exception)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public static bool IsServiceInstalled()
|
|
{
|
|
return ServiceController.GetDevices().Any(sc => sc.ServiceName.Equals(USBMON_SERVICE_NAME_W, StringComparison.InvariantCultureIgnoreCase));
|
|
}
|
|
|
|
public static bool IsVersionSupported(UsbSupVersion version)
|
|
{
|
|
return (version.major == USBMON_MAJOR_VERSION) && (version.minor >= USBMON_MINOR_VERSION);
|
|
}
|
|
|
|
public async Task<UsbSupVersion> GetVersion()
|
|
{
|
|
var output = new byte[Unsafe.SizeOf<UsbSupVersion>()];
|
|
_ = await UsbMonitor.IoControlAsync(SUPUSBFLT_IOCTL.GET_VERSION, null, output);
|
|
return MemoryMarshal.AsRef<UsbSupVersion>(output);
|
|
}
|
|
|
|
public async Task<ulong> AddFilter(ExportedDevice device)
|
|
{
|
|
var filter = UsbFilter.Create(UsbFilterType.CAPTURE);
|
|
filter.SetMatch(UsbFilterIdx.VENDOR_ID, UsbFilterMatch.NUM_EXACT, device.VendorId);
|
|
filter.SetMatch(UsbFilterIdx.PRODUCT_ID, UsbFilterMatch.NUM_EXACT, device.ProductId);
|
|
filter.SetMatch(UsbFilterIdx.DEVICE_REV, UsbFilterMatch.NUM_EXACT, device.BcdDevice);
|
|
filter.SetMatch(UsbFilterIdx.DEVICE_CLASS, UsbFilterMatch.NUM_EXACT, device.DeviceClass);
|
|
filter.SetMatch(UsbFilterIdx.DEVICE_SUB_CLASS, UsbFilterMatch.NUM_EXACT, device.DeviceSubClass);
|
|
filter.SetMatch(UsbFilterIdx.DEVICE_PROTOCOL, UsbFilterMatch.NUM_EXACT, device.DeviceProtocol);
|
|
filter.SetMatch(UsbFilterIdx.PORT, UsbFilterMatch.NUM_EXACT, device.BusId.Port);
|
|
|
|
var output = new byte[Unsafe.SizeOf<UsbSupFltAddOut>()];
|
|
_ = await UsbMonitor.IoControlAsync(SUPUSBFLT_IOCTL.ADD_FILTER, StructToBytes(filter), output);
|
|
ref readonly var fltAddOut = ref MemoryMarshal.AsRef<UsbSupFltAddOut>(output);
|
|
return fltAddOut.rc == 0 ? fltAddOut.uId
|
|
: throw new UnexpectedResultException($"SUPUSBFLT_IOCTL_ADD_FILTER failed with returnCode {fltAddOut.rc}");
|
|
}
|
|
|
|
public async Task RemoveFilter(ulong filterId)
|
|
{
|
|
var output = new byte[sizeof(int)];
|
|
_ = await UsbMonitor.IoControlAsync(SUPUSBFLT_IOCTL.REMOVE_FILTER, BitConverter.GetBytes(filterId), output);
|
|
ref readonly var rc = ref MemoryMarshal.AsRef<int>(output);
|
|
if (rc != 0 /* VINF_SUCCESS */)
|
|
{
|
|
throw new UnexpectedResultException($"SUPUSBFLT_IOCTL_REMOVE_FILTER failed with returnCode {rc}");
|
|
}
|
|
}
|
|
|
|
bool IsDisposed;
|
|
public void Dispose()
|
|
{
|
|
if (!IsDisposed)
|
|
{
|
|
UsbMonitor.Dispose();
|
|
IsDisposed = true;
|
|
}
|
|
}
|
|
}
|