mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-15 03:46:40 +10:00
Project Maintenance
This commit is contained in:
@@ -9,7 +9,6 @@ using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
||||
namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
/// <summary>
|
||||
@@ -21,7 +20,6 @@ namespace MadWizard.WinUSBNet.API
|
||||
public APIException(string message) :
|
||||
base(message)
|
||||
{
|
||||
|
||||
}
|
||||
public APIException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
@@ -41,8 +39,6 @@ namespace MadWizard.WinUSBNet.API
|
||||
public static APIException Win32(string message, int errorCode)
|
||||
{
|
||||
return new APIException(message, new Win32Exception(errorCode));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ namespace MadWizard.WinUSBNet.API
|
||||
/// </summary>
|
||||
internal static partial class DeviceManagement
|
||||
{
|
||||
|
||||
// Get device name from notification message.
|
||||
// Also checks checkGuid with the GUID from the message to check the notification
|
||||
// is for a relevant device. Other messages might be received.
|
||||
@@ -29,14 +28,14 @@ namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
int stringSize;
|
||||
|
||||
DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE_1();
|
||||
DEV_BROADCAST_HDR devBroadcastHeader = new DEV_BROADCAST_HDR();
|
||||
DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new();
|
||||
DEV_BROADCAST_HDR devBroadcastHeader = new();
|
||||
|
||||
// The LParam parameter of Message is a pointer to a DEV_BROADCAST_HDR structure.
|
||||
|
||||
Marshal.PtrToStructure(pDevBroadcastHeader, devBroadcastHeader);
|
||||
|
||||
if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE))
|
||||
if (devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
|
||||
{
|
||||
// The dbch_devicetype parameter indicates that the event applies to a device interface.
|
||||
// So the structure in LParam is actually a DEV_BROADCAST_INTERFACE structure,
|
||||
@@ -60,16 +59,18 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
// Check if message is for the GUID
|
||||
if (devBroadcastDeviceInterface.dbcc_classguid != checkGuid)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Store the device name in a String.
|
||||
string deviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
|
||||
string deviceNameString = new(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
|
||||
|
||||
return deviceNameString;
|
||||
}
|
||||
else if ((devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_VOLUME))
|
||||
else if (devBroadcastHeader.dbch_devicetype == DBT_DEVTYP_VOLUME)
|
||||
{
|
||||
DEV_BROADCAST_VOLUME vol = new DEV_BROADCAST_VOLUME();
|
||||
DEV_BROADCAST_VOLUME vol = new();
|
||||
Marshal.PtrToStructure(pDevBroadcastHeader, vol);
|
||||
Int32 Mask = vol.dbcv_unitmask;
|
||||
Int32 DriveInt = Convert.ToInt32('A') - 1;
|
||||
@@ -86,18 +87,20 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
private static byte[] GetProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property, out int regType)
|
||||
{
|
||||
uint requiredSize;
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, IntPtr.Zero, IntPtr.Zero, 0, out requiredSize))
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, IntPtr.Zero, IntPtr.Zero, 0, out uint requiredSize))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
throw APIException.Win32("Failed to get buffer size for device registry property.");
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[requiredSize];
|
||||
|
||||
if (!SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref deviceInfoData, property, out regType, buffer, (uint)buffer.Length, out requiredSize))
|
||||
{
|
||||
throw APIException.Win32("Failed to get device registry property.");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -113,18 +116,20 @@ namespace MadWizard.WinUSBNet.API
|
||||
// Heathcliff74
|
||||
private static byte[] GetProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, DEVPROPKEY property, out uint propertyType)
|
||||
{
|
||||
int requiredSize;
|
||||
|
||||
if (!SetupDiGetDeviceProperty(deviceInfoSet, ref deviceInfoData, ref property, out propertyType, null, 0, out requiredSize, 0))
|
||||
if (!SetupDiGetDeviceProperty(deviceInfoSet, ref deviceInfoData, ref property, out propertyType, null, 0, out int requiredSize, 0))
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
throw APIException.Win32("Failed to get buffer size for device registry property.");
|
||||
}
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[requiredSize];
|
||||
|
||||
if (!SetupDiGetDeviceProperty(deviceInfoSet, ref deviceInfoData, ref property, out propertyType, buffer, buffer.Length, out requiredSize, 0))
|
||||
{
|
||||
throw APIException.Win32("Failed to get device registry property.");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@@ -132,10 +137,11 @@ namespace MadWizard.WinUSBNet.API
|
||||
// todo: is the queried data always available, or should we check ERROR_INVALID_DATA?
|
||||
private static string GetStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
|
||||
{
|
||||
int regType;
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out int regType);
|
||||
if (regType != (int)RegTypes.REG_SZ)
|
||||
{
|
||||
throw new APIException("Invalid registry type returned for device property.");
|
||||
}
|
||||
|
||||
// sizof(char), 2 bytes, are removed to leave out the string terminator
|
||||
return System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length - sizeof(char));
|
||||
@@ -145,10 +151,11 @@ namespace MadWizard.WinUSBNet.API
|
||||
// todo: is the queried data always available, or should we check ERROR_INVALID_DATA?
|
||||
private static string GetStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, DEVPROPKEY property)
|
||||
{
|
||||
uint propertyType;
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out propertyType);
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out uint propertyType);
|
||||
if (propertyType != 0x00000012) // DEVPROP_TYPE_STRING
|
||||
{
|
||||
throw new APIException("Invalid registry type returned for device property.");
|
||||
}
|
||||
|
||||
// sizof(char), 2 bytes, are removed to leave out the string terminator
|
||||
return System.Text.Encoding.Unicode.GetString(buffer, 0, buffer.Length - sizeof(char));
|
||||
@@ -156,19 +163,19 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
private static string[] GetMultiStringProperty(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, SPDRP property)
|
||||
{
|
||||
int regType;
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out regType);
|
||||
byte[] buffer = GetProperty(deviceInfoSet, deviceInfoData, property, out int regType);
|
||||
if (regType != (int)RegTypes.REG_MULTI_SZ)
|
||||
{
|
||||
throw new APIException("Invalid registry type returned for device property.");
|
||||
}
|
||||
|
||||
string fullString = System.Text.Encoding.Unicode.GetString(buffer);
|
||||
|
||||
return fullString.Split(new char[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
}
|
||||
private static DeviceDetails GetDeviceDetails(string devicePath, IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData)
|
||||
{
|
||||
DeviceDetails details = new DeviceDetails();
|
||||
DeviceDetails details = new();
|
||||
details.DevicePath = devicePath;
|
||||
details.DeviceDescription = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_DEVICEDESC);
|
||||
details.Manufacturer = GetStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_MFG);
|
||||
@@ -183,7 +190,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
string[] hardwareIDs = GetMultiStringProperty(deviceInfoSet, deviceInfoData, SPDRP.SPDRP_HARDWAREID);
|
||||
|
||||
Regex regex = new Regex("^USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})", RegexOptions.IgnoreCase);
|
||||
Regex regex = new("^USB\\\\VID_([0-9A-F]{4})&PID_([0-9A-F]{4})", RegexOptions.IgnoreCase);
|
||||
foreach (string hardwareID in hardwareIDs)
|
||||
{
|
||||
Match match = regex.Match(hardwareID);
|
||||
@@ -204,39 +211,41 @@ namespace MadWizard.WinUSBNet.API
|
||||
return details;
|
||||
}
|
||||
|
||||
|
||||
public static DeviceDetails[] FindDevicesFromGuid(Guid guid)
|
||||
{
|
||||
IntPtr deviceInfoSet = IntPtr.Zero;
|
||||
List<DeviceDetails> deviceList = new List<DeviceDetails>();
|
||||
List<DeviceDetails> deviceList = new();
|
||||
try
|
||||
{
|
||||
deviceInfoSet = SetupDiGetClassDevs(ref guid, IntPtr.Zero, IntPtr.Zero,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (deviceInfoSet == FileIO.INVALID_HANDLE_VALUE)
|
||||
{
|
||||
throw APIException.Win32("Failed to enumerate devices.");
|
||||
}
|
||||
|
||||
int memberIndex = 0;
|
||||
while (true)
|
||||
{
|
||||
// Begin with 0 and increment through the device information set until
|
||||
// no more devices are available.
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
|
||||
SP_DEVICE_INTERFACE_DATA deviceInterfaceData = new();
|
||||
|
||||
// The cbSize element of the deviceInterfaceData structure must be set to
|
||||
// the structure's size in bytes.
|
||||
// The size is 28 bytes for 32-bit code and 32 bytes for 64-bit code.
|
||||
deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);
|
||||
|
||||
bool success;
|
||||
|
||||
success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, memberIndex, ref deviceInterfaceData);
|
||||
bool success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref guid, memberIndex, ref deviceInterfaceData);
|
||||
|
||||
// Find out if a device information set was retrieved.
|
||||
if (!success)
|
||||
{
|
||||
int lastError = Marshal.GetLastWin32Error();
|
||||
if (lastError == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
throw APIException.Win32("Failed to get device interface.");
|
||||
}
|
||||
@@ -255,13 +264,14 @@ namespace MadWizard.WinUSBNet.API
|
||||
if (!success)
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
throw APIException.Win32("Failed to get interface details buffer size.");
|
||||
}
|
||||
}
|
||||
|
||||
IntPtr detailDataBuffer = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
|
||||
// Allocate memory for the SP_DEVICE_INTERFACE_DETAIL_DATA structure using the returned buffer size.
|
||||
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
|
||||
|
||||
@@ -274,10 +284,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
// and the returned required buffer size.
|
||||
|
||||
// build a DevInfo Data structure
|
||||
SP_DEVINFO_DATA da = new SP_DEVINFO_DATA();
|
||||
SP_DEVINFO_DATA da = new();
|
||||
da.cbSize = Marshal.SizeOf(da);
|
||||
|
||||
|
||||
success = SetupDiGetDeviceInterfaceDetail
|
||||
(deviceInfoSet,
|
||||
ref deviceInterfaceData,
|
||||
@@ -287,19 +296,19 @@ namespace MadWizard.WinUSBNet.API
|
||||
ref da);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to get device interface details.");
|
||||
|
||||
}
|
||||
|
||||
// Skip over cbsize (4 bytes) to get the address of the devicePathName.
|
||||
|
||||
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt64() + 4);
|
||||
IntPtr pDevicePathName = new(detailDataBuffer.ToInt64() + 4);
|
||||
string pathName = Marshal.PtrToStringUni(pDevicePathName);
|
||||
|
||||
// Get the String containing the devicePathName.
|
||||
|
||||
DeviceDetails details = GetDeviceDetails(pathName, deviceInfoSet, da);
|
||||
|
||||
|
||||
deviceList.Add(details);
|
||||
}
|
||||
finally
|
||||
@@ -323,11 +332,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
return deviceList.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static void RegisterForDeviceNotifications(IntPtr controlHandle, Guid classGuid, ref IntPtr deviceNotificationHandle)
|
||||
{
|
||||
|
||||
DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DEV_BROADCAST_DEVICEINTERFACE();
|
||||
DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new();
|
||||
IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
@@ -345,7 +352,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
deviceNotificationHandle = RegisterDeviceNotification(controlHandle, devBroadcastDeviceInterfaceBuffer, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
if (deviceNotificationHandle == IntPtr.Zero)
|
||||
{
|
||||
throw APIException.Win32("Failed to register device notification");
|
||||
}
|
||||
|
||||
// Marshal data from the unmanaged block devBroadcastDeviceInterfaceBuffer to
|
||||
// the managed object devBroadcastDeviceInterface
|
||||
@@ -355,14 +364,18 @@ namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
// Free the memory allocated previously by AllocHGlobal.
|
||||
if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
|
||||
{
|
||||
Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void StopDeviceDeviceNotifications(IntPtr deviceNotificationHandle)
|
||||
{
|
||||
if (!DeviceManagement.UnregisterDeviceNotification(deviceNotificationHandle))
|
||||
{
|
||||
throw APIException.Win32("Failed to unregister device notification");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,9 @@ using System.Runtime.InteropServices;
|
||||
namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
/// <summary>
|
||||
/// API declarations relating to device management (SetupDixxx and
|
||||
/// RegisterDeviceNotification functions).
|
||||
/// API declarations relating to device management (SetupDixxx and
|
||||
/// RegisterDeviceNotification functions).
|
||||
/// </summary>
|
||||
|
||||
internal static partial class DeviceManagement
|
||||
{
|
||||
// from dbt.h
|
||||
@@ -86,14 +85,14 @@ namespace MadWizard.WinUSBNet.API
|
||||
private struct SP_DEVICE_INTERFACE_DATA
|
||||
{
|
||||
internal Int32 cbSize;
|
||||
internal System.Guid InterfaceClassGuid;
|
||||
internal Guid InterfaceClassGuid;
|
||||
internal Int32 Flags;
|
||||
internal IntPtr Reserved;
|
||||
}
|
||||
private struct SP_DEVINFO_DATA
|
||||
{
|
||||
internal Int32 cbSize;
|
||||
internal System.Guid ClassGuid;
|
||||
internal Guid ClassGuid;
|
||||
internal Int32 DevInst;
|
||||
internal IntPtr Reserved;
|
||||
}
|
||||
@@ -152,7 +151,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
private static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true)]
|
||||
private static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
|
||||
private static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
private static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, SPDRP Property, out int PropertyRegDataType, byte[] PropertyBuffer, uint PropertyBufferSize, out UInt32 RequiredSize);
|
||||
@@ -161,10 +160,10 @@ namespace MadWizard.WinUSBNet.API
|
||||
private static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, SPDRP Property, IntPtr PropertyRegDataType, IntPtr PropertyBuffer, uint PropertyBufferSize, out UInt32 RequiredSize);
|
||||
|
||||
[DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
static extern unsafe bool SetupDiGetDeviceProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref DEVPROPKEY propertyKey, out UInt32 propertyType, byte[] propertyBuffer, Int32 propertyBufferSize, out int requiredSize, UInt32 flags);
|
||||
private static extern unsafe bool SetupDiGetDeviceProperty(IntPtr deviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, ref DEVPROPKEY propertyKey, out UInt32 propertyType, byte[] propertyBuffer, Int32 propertyBufferSize, out int requiredSize, UInt32 flags);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
|
||||
private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
|
||||
|
||||
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace MadWizard.WinUSBNet.API
|
||||
/// <summary>
|
||||
/// API declarations relating to file I/O (and used by WinUsb).
|
||||
/// </summary>
|
||||
|
||||
sealed internal class FileIO
|
||||
{
|
||||
public const Int32 FILE_ATTRIBUTE_NORMAL = 0X80;
|
||||
@@ -27,7 +26,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
public const Int32 FILE_SHARE_WRITE = 2;
|
||||
public const UInt32 GENERIC_READ = 0X80000000;
|
||||
public const UInt32 GENERIC_WRITE = 0X40000000;
|
||||
public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
|
||||
public static readonly IntPtr INVALID_HANDLE_VALUE = new(-1);
|
||||
public const Int32 OPEN_EXISTING = 3;
|
||||
|
||||
public const Int32 ERROR_IO_PENDING = 997;
|
||||
@@ -35,5 +34,4 @@ namespace MadWizard.WinUSBNet.API
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
public static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, Int32 hTemplateFile);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
/// <summary>
|
||||
/// Wrapper for a WinUSB device dealing with the WinUSB and additional interface handles
|
||||
/// </summary>
|
||||
partial class WinUSBDevice : IDisposable
|
||||
internal partial class WinUSBDevice : IDisposable
|
||||
{
|
||||
private bool _disposed = false;
|
||||
private SafeFileHandle _deviceHandle;
|
||||
@@ -44,7 +44,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
private void CheckNotDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException("USB device object has been disposed.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check if not disposed on methods (although this is already checked by USBDevice)
|
||||
@@ -52,13 +54,18 @@ namespace MadWizard.WinUSBNet.API
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
// Dispose managed resources
|
||||
if (_deviceHandle != null && !_deviceHandle.IsInvalid)
|
||||
if (_deviceHandle?.IsInvalid == false)
|
||||
{
|
||||
_deviceHandle.Dispose();
|
||||
}
|
||||
|
||||
_deviceHandle = null;
|
||||
}
|
||||
|
||||
@@ -77,40 +84,51 @@ namespace MadWizard.WinUSBNet.API
|
||||
_addInterfaces = null;
|
||||
}
|
||||
if (_winUsbHandle != IntPtr.Zero)
|
||||
{
|
||||
WinUsb_Free(_winUsbHandle);
|
||||
}
|
||||
|
||||
_winUsbHandle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public USB_DEVICE_DESCRIPTOR GetDeviceDescriptor()
|
||||
{
|
||||
USB_DEVICE_DESCRIPTOR deviceDesc;
|
||||
uint transfered;
|
||||
uint size = (uint)Marshal.SizeOf(typeof(USB_DEVICE_DESCRIPTOR));
|
||||
bool success = WinUsb_GetDescriptor(_winUsbHandle, USB_DEVICE_DESCRIPTOR_TYPE,
|
||||
0, 0, out deviceDesc, size, out transfered);
|
||||
0, 0, out USB_DEVICE_DESCRIPTOR deviceDesc, size, out uint transfered);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to get USB device descriptor.");
|
||||
}
|
||||
|
||||
if (transfered != size)
|
||||
{
|
||||
throw APIException.Win32("Incomplete USB device descriptor.");
|
||||
}
|
||||
|
||||
return deviceDesc;
|
||||
}
|
||||
|
||||
private int ReadStringDescriptor(byte index, ushort languageID, byte[] buffer)
|
||||
{
|
||||
uint transfered;
|
||||
bool success = WinUsb_GetDescriptor(_winUsbHandle, USB_STRING_DESCRIPTOR_TYPE,
|
||||
index, languageID, buffer, (uint)buffer.Length, out transfered);
|
||||
index, languageID, buffer, (uint)buffer.Length, out uint transfered);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to get USB string descriptor (" + index + ").");
|
||||
}
|
||||
|
||||
if (transfered == 0)
|
||||
{
|
||||
throw new APIException("No data returned when reading USB descriptor.");
|
||||
}
|
||||
|
||||
int length = buffer[0];
|
||||
if (length != transfered)
|
||||
{
|
||||
throw new APIException("Unexpected length when reading USB descriptor.");
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
@@ -120,7 +138,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
int length = ReadStringDescriptor(0, 0, buffer);
|
||||
length -= 2; // Skip length byte and descriptor type
|
||||
if (length < 0 || (length % 2) != 0)
|
||||
{
|
||||
throw new APIException("Unexpected length when reading supported languages.");
|
||||
}
|
||||
|
||||
ushort[] langIDs = new ushort[length / 2];
|
||||
Buffer.BlockCopy(buffer, 2, langIDs, 0, length);
|
||||
@@ -133,7 +153,10 @@ namespace MadWizard.WinUSBNet.API
|
||||
int length = ReadStringDescriptor(index, languageID, buffer);
|
||||
length -= 2; // Skip length byte and descriptor type
|
||||
if (length < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
char[] chars = System.Text.Encoding.Unicode.GetChars(buffer, 2, length);
|
||||
return new string(chars);
|
||||
}
|
||||
@@ -151,26 +174,30 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
bool success = WinUsb_ControlTransfer(_winUsbHandle, setupPacket, data, length, ref bytesReturned, IntPtr.Zero);
|
||||
if (!success) // todo check bytes returned?
|
||||
{
|
||||
throw APIException.Win32("Control transfer on WinUSB device failed.");
|
||||
}
|
||||
|
||||
return (int)bytesReturned;
|
||||
}
|
||||
|
||||
|
||||
public void OpenDevice(string devicePathName)
|
||||
{
|
||||
try
|
||||
{
|
||||
_deviceHandle = FileIO.CreateFile(devicePathName,
|
||||
(FileIO.GENERIC_WRITE | FileIO.GENERIC_READ),
|
||||
FileIO.GENERIC_WRITE | FileIO.GENERIC_READ,
|
||||
FileIO.FILE_SHARE_READ | FileIO.FILE_SHARE_WRITE,
|
||||
IntPtr.Zero,
|
||||
FileIO.OPEN_EXISTING,
|
||||
FileIO.FILE_ATTRIBUTE_NORMAL | FileIO.FILE_FLAG_OVERLAPPED,
|
||||
0);
|
||||
if (_deviceHandle.IsInvalid)
|
||||
{
|
||||
throw APIException.Win32("Failed to open WinUSB device handle.");
|
||||
InitializeDevice();
|
||||
}
|
||||
|
||||
InitializeDevice();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -187,7 +214,10 @@ namespace MadWizard.WinUSBNet.API
|
||||
private IntPtr InterfaceHandle(int index)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
return _winUsbHandle;
|
||||
}
|
||||
|
||||
return _addInterfaces[index - 1];
|
||||
}
|
||||
|
||||
@@ -195,7 +225,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1 + (_addInterfaces == null ? 0 : _addInterfaces.Length);
|
||||
return 1 + ((_addInterfaces?.Length) ?? 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,31 +234,33 @@ namespace MadWizard.WinUSBNet.API
|
||||
var pipeList = new List<WINUSB_PIPE_INFORMATION>();
|
||||
bool success = WinUsb_QueryInterfaceSettings(InterfaceHandle(interfaceIndex), 0, out descriptor);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to get WinUSB device interface descriptor.");
|
||||
}
|
||||
|
||||
IntPtr interfaceHandle = InterfaceHandle(interfaceIndex);
|
||||
for (byte pipeIdx = 0; pipeIdx < descriptor.bNumEndpoints; pipeIdx++)
|
||||
{
|
||||
WINUSB_PIPE_INFORMATION pipeInfo;
|
||||
success = WinUsb_QueryPipe(interfaceHandle, 0, pipeIdx, out pipeInfo);
|
||||
success = WinUsb_QueryPipe(interfaceHandle, 0, pipeIdx, out WINUSB_PIPE_INFORMATION pipeInfo);
|
||||
|
||||
pipeList.Add(pipeInfo);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to get WinUSB device pipe information.");
|
||||
}
|
||||
}
|
||||
pipes = pipeList.ToArray();
|
||||
|
||||
}
|
||||
private void InitializeDevice()
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = WinUsb_Initialize(_deviceHandle, ref _winUsbHandle);
|
||||
bool success = WinUsb_Initialize(_deviceHandle, ref _winUsbHandle);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to initialize WinUSB handle. Device might not be connected.");
|
||||
}
|
||||
|
||||
List<IntPtr> interfaces = new List<IntPtr>();
|
||||
List<IntPtr> interfaces = new();
|
||||
byte numAddInterfaces = 0;
|
||||
byte idx = 0;
|
||||
|
||||
@@ -241,7 +273,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
if (!success)
|
||||
{
|
||||
if (Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
throw APIException.Win32("Failed to enumerate interfaces for WinUSB device.");
|
||||
}
|
||||
@@ -278,7 +312,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to read pipe on WinUSB device.");
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe void HandleOverlappedAPI(bool success, string errorMessage, NativeOverlapped* pOverlapped, USBAsyncResult result, int bytesTransfered)
|
||||
@@ -301,12 +337,11 @@ namespace MadWizard.WinUSBNet.API
|
||||
result.OnCompletion(true, null, bytesTransfered, false);
|
||||
// is the callback still called in this case?? todo
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void ReadPipeOverlapped(int ifaceIndex, byte pipeID, byte[] buffer, int offset, int bytesToRead, USBAsyncResult result)
|
||||
{
|
||||
Overlapped overlapped = new Overlapped();
|
||||
Overlapped overlapped = new();
|
||||
|
||||
overlapped.AsyncResult = result;
|
||||
|
||||
@@ -329,7 +364,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
|
||||
public void WriteOverlapped(int ifaceIndex, byte pipeID, byte[] buffer, int offset, int bytesToWrite, USBAsyncResult result)
|
||||
{
|
||||
Overlapped overlapped = new Overlapped();
|
||||
Overlapped overlapped = new();
|
||||
overlapped.AsyncResult = result;
|
||||
|
||||
unsafe
|
||||
@@ -347,12 +382,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
out bytesWritten, pOverlapped);
|
||||
}
|
||||
HandleOverlappedAPI(success, "Failed to asynchronously write pipe on WinUSB device.", pOverlapped, result, (int)bytesWritten);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ControlTransferOverlapped(byte requestType, byte request, ushort value, ushort index, ushort length, byte[] data, USBAsyncResult result)
|
||||
{
|
||||
uint bytesReturned = 0;
|
||||
@@ -364,7 +396,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
setupPacket.Index = index;
|
||||
setupPacket.Length = length;
|
||||
|
||||
Overlapped overlapped = new Overlapped();
|
||||
Overlapped overlapped = new();
|
||||
overlapped.AsyncResult = result;
|
||||
|
||||
unsafe
|
||||
@@ -405,16 +437,18 @@ namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
bool success = WinUsb_AbortPipe(InterfaceHandle(ifaceIndex), pipeID);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to abort pipe on WinUSB device.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetPipe(int ifaceIndex, byte pipeID)
|
||||
{
|
||||
bool success = WinUsb_ResetPipe(InterfaceHandle(ifaceIndex), pipeID);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to reset pipe on WinUSB device.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void WritePipe(int ifaceIndex, byte pipeID, byte[] buffer, int offset, int length)
|
||||
@@ -432,15 +466,18 @@ namespace MadWizard.WinUSBNet.API
|
||||
}
|
||||
}
|
||||
if (!success || (bytesWritten != length))
|
||||
{
|
||||
throw APIException.Win32("Failed to write pipe on WinUSB device.");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void FlushPipe(int ifaceIndex, byte pipeID)
|
||||
{
|
||||
bool success = WinUsb_FlushPipe(InterfaceHandle(ifaceIndex), pipeID);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to flush pipe on WinUSB device.");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetPipePolicy(int ifaceIndex, byte pipeID, POLICY_TYPE policyType, bool value)
|
||||
@@ -448,41 +485,44 @@ namespace MadWizard.WinUSBNet.API
|
||||
byte byteVal = (byte)(value ? 1 : 0);
|
||||
bool success = WinUsb_SetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, 1, ref byteVal);
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to set WinUSB pipe policy.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetPipePolicy(int ifaceIndex, byte pipeID, POLICY_TYPE policyType, uint value)
|
||||
{
|
||||
|
||||
bool success = WinUsb_SetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, 4, ref value);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw APIException.Win32("Failed to set WinUSB pipe policy.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool GetPipePolicyBool(int ifaceIndex, byte pipeID, POLICY_TYPE policyType)
|
||||
{
|
||||
byte result;
|
||||
uint length = 1;
|
||||
|
||||
bool success = WinUsb_GetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, ref length, out result);
|
||||
bool success = WinUsb_GetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, ref length, out byte result);
|
||||
if (!success || length != 1)
|
||||
{
|
||||
throw APIException.Win32("Failed to get WinUSB pipe policy.");
|
||||
}
|
||||
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
|
||||
public uint GetPipePolicyUInt(int ifaceIndex, byte pipeID, POLICY_TYPE policyType)
|
||||
{
|
||||
|
||||
uint result;
|
||||
uint length = 4;
|
||||
bool success = WinUsb_GetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, ref length, out result);
|
||||
bool success = WinUsb_GetPipePolicy(InterfaceHandle(ifaceIndex), pipeID, (uint)policyType, ref length, out uint result);
|
||||
|
||||
if (!success || length != 4)
|
||||
{
|
||||
throw APIException.Win32("Failed to get WinUSB pipe policy.");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ using System.Threading;
|
||||
namespace MadWizard.WinUSBNet.API
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct USB_DEVICE_DESCRIPTOR
|
||||
internal struct USB_DEVICE_DESCRIPTOR
|
||||
{
|
||||
public byte bLength;
|
||||
public byte bDescriptorType;
|
||||
@@ -36,7 +36,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct USB_CONFIGURATION_DESCRIPTOR
|
||||
internal struct USB_CONFIGURATION_DESCRIPTOR
|
||||
{
|
||||
public byte bLength;
|
||||
public byte bDescriptorType;
|
||||
@@ -49,7 +49,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct USB_INTERFACE_DESCRIPTOR
|
||||
internal struct USB_INTERFACE_DESCRIPTOR
|
||||
{
|
||||
public byte bLength;
|
||||
public byte bDescriptorType;
|
||||
@@ -61,7 +61,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
public byte bInterfaceProtocol;
|
||||
public byte iInterface;
|
||||
};
|
||||
enum USBD_PIPE_TYPE : int
|
||||
internal enum USBD_PIPE_TYPE : int
|
||||
{
|
||||
UsbdPipeTypeControl,
|
||||
UsbdPipeTypeIsochronous,
|
||||
@@ -69,7 +69,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
UsbdPipeTypeInterrupt,
|
||||
}
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct WINUSB_PIPE_INFORMATION
|
||||
internal struct WINUSB_PIPE_INFORMATION
|
||||
{
|
||||
public USBD_PIPE_TYPE PipeType;
|
||||
public byte PipeId;
|
||||
@@ -77,7 +77,7 @@ namespace MadWizard.WinUSBNet.API
|
||||
public byte Interval;
|
||||
}
|
||||
|
||||
enum POLICY_TYPE : int
|
||||
internal enum POLICY_TYPE : int
|
||||
{
|
||||
SHORT_PACKET_TERMINATE = 1,
|
||||
AUTO_CLEAR_STALL,
|
||||
@@ -88,10 +88,9 @@ namespace MadWizard.WinUSBNet.API
|
||||
RAW_IO,
|
||||
}
|
||||
|
||||
|
||||
partial class WinUSBDevice
|
||||
internal partial class WinUSBDevice
|
||||
{
|
||||
private const UInt32 DEVICE_SPEED = ((UInt32)(1));
|
||||
private const UInt32 DEVICE_SPEED = 1;
|
||||
|
||||
private enum USB_DEVICE_SPEED : int
|
||||
{
|
||||
@@ -163,19 +162,15 @@ namespace MadWizard.WinUSBNet.API
|
||||
[DllImport("winusb.dll", SetLastError = true)]
|
||||
private static unsafe extern bool WinUsb_WritePipe(IntPtr InterfaceHandle, byte PipeID, byte* pBuffer, uint BufferLength, out uint LengthTransferred, NativeOverlapped* pOverlapped);
|
||||
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static unsafe extern bool CancelIo(IntPtr hFile);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
private static unsafe extern bool CancelIoEx(IntPtr hFile, NativeOverlapped* pOverlapped);
|
||||
|
||||
|
||||
[DllImport("winusb.dll", SetLastError = true)]
|
||||
private static unsafe extern bool WinUsb_ResetPipe(IntPtr InterfaceHandle, byte PipeID);
|
||||
|
||||
|
||||
|
||||
[DllImport("winusb.dll", SetLastError = true)]
|
||||
private static extern bool WinUsb_FlushPipe(IntPtr InterfaceHandle, byte PipeID);
|
||||
|
||||
@@ -200,6 +195,5 @@ namespace MadWizard.WinUSBNet.API
|
||||
private const int USB_STRING_DESCRIPTOR_TYPE = 0x03;
|
||||
|
||||
private const int ERROR_NO_MORE_ITEMS = 259;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user