mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-14 03:16: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;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
// TODO: disposed exception when disposed
|
||||
|
||||
private USBNotifier _notifier;
|
||||
private readonly USBNotifier _notifier;
|
||||
private Guid _guid;
|
||||
private IntPtr _notifyHandle;
|
||||
private readonly IntPtr _notifyHandle;
|
||||
|
||||
public DeviceNotifyHook(USBNotifier notifier, Guid guid)
|
||||
{
|
||||
@@ -31,8 +31,14 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
IntPtr hWnd = IntPtr.Zero;
|
||||
if (Application.Current.MainWindow != null)
|
||||
{
|
||||
hWnd = new WindowInteropHelper(Application.Current.MainWindow).Handle;
|
||||
if (hWnd == IntPtr.Zero) throw new USBException("Main window not loaded yet. Cannot connect with USB yet.");
|
||||
}
|
||||
|
||||
if (hWnd == IntPtr.Zero)
|
||||
{
|
||||
throw new USBException("Main window not loaded yet. Cannot connect with USB yet.");
|
||||
}
|
||||
|
||||
API.DeviceManagement.RegisterForDeviceNotifications(hWnd, _guid, ref _notifyHandle);
|
||||
|
||||
@@ -125,13 +131,11 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
// Listen for operating system messages
|
||||
|
||||
switch (msg)
|
||||
return msg switch
|
||||
{
|
||||
case API.DeviceManagement.WM_DEVICECHANGE:
|
||||
return (IntPtr)_notifier.HandleDeviceChange(msg, wParam, lParam);
|
||||
//break;
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
API.DeviceManagement.WM_DEVICECHANGE => (IntPtr)_notifier.HandleDeviceChange(msg, wParam, lParam),
|
||||
_ => IntPtr.Zero,
|
||||
};
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
@@ -162,26 +166,29 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
*/
|
||||
|
||||
Action RemoveHookAction = () =>
|
||||
void RemoveHookAction()
|
||||
{
|
||||
if (Application.Current.MainWindow != null)
|
||||
{
|
||||
HwndSource source = PresentationSource.FromVisual(Application.Current.MainWindow) as HwndSource;
|
||||
source.RemoveHook(WndProc);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (Application.Current != null)
|
||||
{
|
||||
if (Application.Current.Dispatcher.Thread.ManagedThreadId == System.Threading.Thread.CurrentThread.ManagedThreadId)
|
||||
{
|
||||
RemoveHookAction();
|
||||
}
|
||||
else
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(RemoveHookAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,5 +73,4 @@ namespace MadWizard.WinUSBNet
|
||||
/// <summary>Vendor specific base class (0xFF)</summary>
|
||||
VendorSpecific = 0xFF,
|
||||
};
|
||||
|
||||
}
|
||||
+11
-17
@@ -11,8 +11,7 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
internal class USBAsyncResult : IAsyncResult, IDisposable
|
||||
{
|
||||
private object _stateObject;
|
||||
private AsyncCallback _userCallback;
|
||||
private readonly AsyncCallback _userCallback;
|
||||
private bool _completed;
|
||||
private bool _completedSynchronously;
|
||||
private ManualResetEvent _waitEvent;
|
||||
@@ -21,20 +20,14 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
public USBAsyncResult(AsyncCallback userCallback, object stateObject)
|
||||
{
|
||||
_stateObject = stateObject;
|
||||
AsyncState = stateObject;
|
||||
_userCallback = userCallback;
|
||||
_completedSynchronously = false;
|
||||
_completed = false;
|
||||
_waitEvent = null;
|
||||
}
|
||||
|
||||
public object AsyncState
|
||||
{
|
||||
get
|
||||
{
|
||||
return _stateObject;
|
||||
}
|
||||
}
|
||||
public object AsyncState { get; }
|
||||
|
||||
public Exception Error
|
||||
{
|
||||
@@ -57,7 +50,9 @@ namespace MadWizard.WinUSBNet
|
||||
lock (this)
|
||||
{
|
||||
if (_waitEvent == null)
|
||||
{
|
||||
_waitEvent = new ManualResetEvent(_completed);
|
||||
}
|
||||
}
|
||||
return _waitEvent;
|
||||
}
|
||||
@@ -99,17 +94,19 @@ namespace MadWizard.WinUSBNet
|
||||
_completed = true;
|
||||
_error = error;
|
||||
_bytesTransfered = bytesTransfered;
|
||||
if (_waitEvent != null)
|
||||
_waitEvent.Set();
|
||||
_waitEvent?.Set();
|
||||
}
|
||||
if (_userCallback != null)
|
||||
{
|
||||
if (synchronousCallback)
|
||||
{
|
||||
RunCallback(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
ThreadPool.QueueUserWorkItem(RunCallback);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private void RunCallback(object state)
|
||||
{
|
||||
@@ -122,12 +119,9 @@ namespace MadWizard.WinUSBNet
|
||||
// Cleanup managed resources
|
||||
lock (this)
|
||||
{
|
||||
if (_waitEvent != null)
|
||||
_waitEvent.Close();
|
||||
_waitEvent?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+81
-53
@@ -15,7 +15,6 @@ namespace MadWizard.WinUSBNet
|
||||
/// </summary>
|
||||
public class USBDevice : IDisposable
|
||||
{
|
||||
private API.WinUSBDevice _wuDevice = null;
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -60,7 +59,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBDeviceDescriptor Descriptor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,12 +99,13 @@ namespace MadWizard.WinUSBNet
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (_wuDevice != null)
|
||||
_wuDevice.Dispose();
|
||||
InternalDevice?.Dispose();
|
||||
}
|
||||
|
||||
// Clean unmanaged resources here.
|
||||
@@ -129,32 +128,26 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
//WPinternals.LogFile.LogException(Ex);
|
||||
}
|
||||
_wuDevice = new API.WinUSBDevice();
|
||||
InternalDevice = new API.WinUSBDevice();
|
||||
try
|
||||
{
|
||||
_wuDevice.OpenDevice(devicePathName);
|
||||
InternalDevice.OpenDevice(devicePathName);
|
||||
InitializeInterfaces();
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
_wuDevice.Dispose();
|
||||
InternalDevice.Dispose();
|
||||
throw new USBException("Failed to open device.", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal API.WinUSBDevice InternalDevice
|
||||
{
|
||||
get
|
||||
{
|
||||
return _wuDevice;
|
||||
}
|
||||
}
|
||||
internal API.WinUSBDevice InternalDevice { get; } = null;
|
||||
|
||||
private void InitializeInterfaces()
|
||||
{
|
||||
int numInterfaces = _wuDevice.InterfaceCount;
|
||||
int numInterfaces = InternalDevice.InterfaceCount;
|
||||
|
||||
List<USBPipe> allPipes = new List<USBPipe>();
|
||||
List<USBPipe> allPipes = new();
|
||||
InputPipe = null;
|
||||
OutputPipe = null;
|
||||
|
||||
@@ -162,22 +155,27 @@ namespace MadWizard.WinUSBNet
|
||||
// UsbEndpoint
|
||||
for (int i = 0; i < numInterfaces; i++)
|
||||
{
|
||||
API.USB_INTERFACE_DESCRIPTOR descriptor;
|
||||
API.WINUSB_PIPE_INFORMATION[] pipesInfo;
|
||||
_wuDevice.GetInterfaceInfo(i, out descriptor, out pipesInfo);
|
||||
InternalDevice.GetInterfaceInfo(i, out API.USB_INTERFACE_DESCRIPTOR descriptor, out API.WINUSB_PIPE_INFORMATION[] pipesInfo);
|
||||
USBPipe[] interfacePipes = new USBPipe[pipesInfo.Length];
|
||||
for(int k=0;k<pipesInfo.Length;k++)
|
||||
{
|
||||
USBPipe pipe = new USBPipe(this, pipesInfo[k]);
|
||||
USBPipe pipe = new(this, pipesInfo[k]);
|
||||
interfacePipes[k] = pipe;
|
||||
allPipes.Add(pipe);
|
||||
if (Convert.ToBoolean((pipesInfo[k].PipeId & 0x80)) && (InputPipe == null)) InputPipe = pipe;
|
||||
if (!Convert.ToBoolean((pipesInfo[k].PipeId & 0x80)) && (OutputPipe == null)) OutputPipe = pipe;
|
||||
if (Convert.ToBoolean(pipesInfo[k].PipeId & 0x80) && (InputPipe == null))
|
||||
{
|
||||
InputPipe = pipe;
|
||||
}
|
||||
|
||||
if (!Convert.ToBoolean(pipesInfo[k].PipeId & 0x80) && (OutputPipe == null))
|
||||
{
|
||||
OutputPipe = pipe;
|
||||
}
|
||||
}
|
||||
// TODO:
|
||||
//if (descriptor.iInterface != 0)
|
||||
// _wuDevice.GetStringDescriptor(descriptor.iInterface);
|
||||
USBPipeCollection pipeCollection = new USBPipeCollection(interfacePipes);
|
||||
USBPipeCollection pipeCollection = new(interfacePipes);
|
||||
interfaces[i] = new USBInterface(this, i, descriptor, pipeCollection);
|
||||
}
|
||||
Pipes = new USBPipeCollection(allPipes.ToArray());
|
||||
@@ -187,13 +185,24 @@ namespace MadWizard.WinUSBNet
|
||||
private void CheckControlParams(int value, int index, byte[] buffer, int length)
|
||||
{
|
||||
if (value < ushort.MinValue || value > ushort.MaxValue)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Value parameter out of range.");
|
||||
}
|
||||
|
||||
if (index < ushort.MinValue || index > ushort.MaxValue)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index), "Index parameter out of range.");
|
||||
}
|
||||
|
||||
if (length > buffer.Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length), "Length parameter is larger than the size of the buffer.");
|
||||
}
|
||||
|
||||
if (length > ushort.MaxValue)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(length), "Length too large");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -207,22 +216,31 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
byte PipeID = 0;
|
||||
if (InputPipe != null)
|
||||
{
|
||||
PipeID = InputPipe.Address;
|
||||
return (int)_wuDevice.GetPipePolicyUInt(0, 0x00, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT);
|
||||
}
|
||||
|
||||
return (int)InternalDevice.GetPipePolicyUInt(0, 0x00, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Control pipe timeout cannot be negative.");
|
||||
}
|
||||
//_wuDevice.SetPipePolicy(0, 0x00, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
if (InputPipe != null)
|
||||
_wuDevice.SetPipePolicy(0, InputPipe.Address, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
{
|
||||
InternalDevice.SetPipePolicy(0, InputPipe.Address, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
}
|
||||
|
||||
if (OutputPipe != null)
|
||||
_wuDevice.SetPipePolicy(0, OutputPipe.Address, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
{
|
||||
InternalDevice.SetPipePolicy(0, OutputPipe.Address, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a control transfer over the default control endpoint. This method allows both IN and OUT direction transfers, depending
|
||||
/// on the highest bit of the <paramref name="requestType"/> parameter. Alternatively, <see cref="ControlIn(byte,byte,int,int,byte[],int)"/> and
|
||||
@@ -246,7 +264,7 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
try
|
||||
{
|
||||
return _wuDevice.ControlTransfer(requestType, request, (ushort)value, (ushort)index, (ushort)length, buffer);
|
||||
return InternalDevice.ControlTransfer(requestType, request, (ushort)value, (ushort)index, (ushort)length, buffer);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
@@ -283,22 +301,20 @@ namespace MadWizard.WinUSBNet
|
||||
CheckNotDisposed();
|
||||
CheckControlParams(value, index, buffer, length);
|
||||
|
||||
USBAsyncResult result = new USBAsyncResult(userCallback, stateObject);
|
||||
USBAsyncResult result = new(userCallback, stateObject);
|
||||
|
||||
try
|
||||
{
|
||||
_wuDevice.ControlTransferOverlapped(requestType, request, (ushort)value, (ushort)index, (ushort)length, buffer, result);
|
||||
InternalDevice.ControlTransferOverlapped(requestType, request, (ushort)value, (ushort)index, (ushort)length, buffer, result);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
if (result != null)
|
||||
result.Dispose();
|
||||
result?.Dispose();
|
||||
throw new USBException("Asynchronous control transfer failed", e);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (result != null)
|
||||
result.Dispose();
|
||||
result?.Dispose();
|
||||
throw;
|
||||
}
|
||||
return result;
|
||||
@@ -331,7 +347,6 @@ namespace MadWizard.WinUSBNet
|
||||
return BeginControlTransfer(requestType, request, value, index, buffer, buffer.Length, userCallback, stateObject);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a pending asynchronous control transfer to complete.
|
||||
/// </summary>
|
||||
@@ -346,19 +361,28 @@ namespace MadWizard.WinUSBNet
|
||||
public int EndControlTransfer(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult == null)
|
||||
{
|
||||
throw new NullReferenceException("asyncResult cannot be null");
|
||||
}
|
||||
|
||||
if (!(asyncResult is USBAsyncResult))
|
||||
{
|
||||
throw new ArgumentException("AsyncResult object was not created by calling one of the BeginControl* methods on this class.");
|
||||
}
|
||||
|
||||
// todo: check duplicate end control
|
||||
USBAsyncResult result = (USBAsyncResult)asyncResult;
|
||||
try
|
||||
{
|
||||
if (!result.IsCompleted)
|
||||
{
|
||||
result.AsyncWaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
if (result.Error != null)
|
||||
{
|
||||
throw new USBException("Asynchronous control transfer from pipe has failed.", result.Error);
|
||||
}
|
||||
|
||||
return result.BytesTransfered;
|
||||
}
|
||||
@@ -366,10 +390,8 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
result.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a control transfer over the default control endpoint. This method allows both IN and OUT direction transfers, depending
|
||||
/// on the highest bit of the <paramref name="requestType"/> parameter). Alternatively, <see cref="ControlIn(byte,byte,int,int,byte[])"/> and
|
||||
@@ -402,19 +424,23 @@ namespace MadWizard.WinUSBNet
|
||||
public void ControlTransfer(byte requestType, byte request, int value, int index)
|
||||
{
|
||||
// TODO: null instead of empty buffer. But overlapped code would have to be fixed for this (no buffer to pin)
|
||||
ControlTransfer(requestType, request, value, index, new byte[0], 0);
|
||||
ControlTransfer(requestType, request, value, index, Array.Empty<byte>(), 0);
|
||||
}
|
||||
|
||||
private void CheckIn(byte requestType)
|
||||
{
|
||||
if ((requestType & 0x80) == 0) // Host to device?
|
||||
{
|
||||
throw new ArgumentException("Request type is not IN.");
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckOut(byte requestType)
|
||||
{
|
||||
if ((requestType & 0x80) == 0x80) // Device to host?
|
||||
{
|
||||
throw new ArgumentException("Request type is not OUT.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -445,7 +471,6 @@ namespace MadWizard.WinUSBNet
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a control transfer over the default control endpoint. The request should have an IN direction (specified by the highest bit
|
||||
/// of the <paramref name="requestType"/> parameter).
|
||||
@@ -493,7 +518,7 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
CheckIn(requestType);
|
||||
// TODO: null instead of empty buffer. But overlapped code would have to be fixed for this (no buffer to pin)
|
||||
ControlTransfer(requestType, request, value, index, new byte[0]);
|
||||
ControlTransfer(requestType, request, value, index, Array.Empty<byte>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -541,11 +566,9 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
CheckOut(requestType);
|
||||
// TODO: null instead of empty buffer. But overlapped code would have to be fixed for this (no buffer to pin)
|
||||
ControlTransfer(requestType, request, value, index, new byte[0]);
|
||||
ControlTransfer(requestType, request, value, index, Array.Empty<byte>());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initiates an asynchronous control transfer without a data stage over the default control endpoint. This method allows both IN and OUT direction transfers, depending
|
||||
/// on the highest bit of the <paramref name="requestType"/> parameter. Alternatively, <see cref="BeginControlIn(byte,byte,int,int,byte[],int,AsyncCallback,object)"/> and
|
||||
@@ -568,11 +591,9 @@ namespace MadWizard.WinUSBNet
|
||||
public IAsyncResult BeginControlTransfer(byte requestType, byte request, int value, int index, AsyncCallback userCallback, object stateObject)
|
||||
{
|
||||
// TODO: null instead of empty buffer. But overlapped code would have to be fixed for this (no buffer to pin)
|
||||
return BeginControlTransfer(requestType, request, value, index, new byte[0], 0, userCallback, stateObject);
|
||||
return BeginControlTransfer(requestType, request, value, index, Array.Empty<byte>(), 0, userCallback, stateObject);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Initiates an asynchronous control transfer over the default control endpoint. The request should have an IN direction (specified by the highest bit
|
||||
/// of the <paramref name="requestType"/> parameter).</summary>
|
||||
@@ -711,14 +732,15 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
CheckOut(requestType);
|
||||
// TODO: null instead of empty buffer. But overlapped code would have to be fixed for this (no buffer to pin)
|
||||
return BeginControlTransfer(requestType, request, value, index, new byte[0], userCallback, stateObject);
|
||||
return BeginControlTransfer(requestType, request, value, index, Array.Empty<byte>(), userCallback, stateObject);
|
||||
}
|
||||
|
||||
|
||||
private void CheckNotDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException("USB device object has been disposed.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -766,8 +788,9 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
API.DeviceDetails[] detailList = API.DeviceManagement.FindDevicesFromGuid(guid);
|
||||
if (detailList.Length == 0)
|
||||
{
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
return new USBDevice(detailList[0].DevicePath);
|
||||
}
|
||||
@@ -781,7 +804,6 @@ namespace MadWizard.WinUSBNet
|
||||
/// no device with the given GUID could be found null is returned.</returns>
|
||||
public static USBDevice GetSingleDevice(string guidString)
|
||||
{
|
||||
|
||||
return USBDevice.GetSingleDevice(new Guid(guidString));
|
||||
}
|
||||
|
||||
@@ -790,7 +812,7 @@ namespace MadWizard.WinUSBNet
|
||||
try
|
||||
{
|
||||
USBDeviceDescriptor descriptor;
|
||||
using (API.WinUSBDevice wuDevice = new API.WinUSBDevice())
|
||||
using (API.WinUSBDevice wuDevice = new())
|
||||
{
|
||||
wuDevice.OpenDevice(devicePath);
|
||||
API.USB_DEVICE_DESCRIPTOR deviceDesc = wuDevice.GetDeviceDescriptor();
|
||||
@@ -799,7 +821,9 @@ namespace MadWizard.WinUSBNet
|
||||
ushort[] langIDs = wuDevice.GetSupportedLanguageIDs();
|
||||
ushort langID = 0;
|
||||
if (langIDs.Length > 0)
|
||||
{
|
||||
langID = langIDs[0];
|
||||
}
|
||||
|
||||
string manufacturer = null, product = null, serialNumber = null;
|
||||
byte idx = 0;
|
||||
@@ -808,7 +832,9 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
idx = deviceDesc.iManufacturer;
|
||||
if (idx > 0)
|
||||
{
|
||||
manufacturer = wuDevice.GetStringDescriptor(idx, langID);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
@@ -816,7 +842,9 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
idx = deviceDesc.iProduct;
|
||||
if (idx > 0)
|
||||
{
|
||||
product = wuDevice.GetStringDescriptor(idx, langID);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
@@ -824,20 +852,20 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
idx = deviceDesc.iSerialNumber;
|
||||
if (idx > 0)
|
||||
{
|
||||
serialNumber = wuDevice.GetStringDescriptor(idx, langID);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
descriptor = new USBDeviceDescriptor(devicePath, deviceDesc, manufacturer, product, serialNumber);
|
||||
}
|
||||
return descriptor;
|
||||
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
throw new USBException("Failed to retrieve device descriptor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,33 +17,32 @@ namespace MadWizard.WinUSBNet
|
||||
/// <summary>
|
||||
/// Windows path name for the USB device
|
||||
/// </summary>
|
||||
public string PathName { get; private set; }
|
||||
public string PathName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// USB vendor ID (VID) of the device
|
||||
/// </summary>
|
||||
public int VID { get; private set; }
|
||||
public int VID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// USB product ID (PID) of the device
|
||||
/// </summary>
|
||||
public int PID { get; private set; }
|
||||
public int PID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Manufacturer name, or null if not available
|
||||
/// </summary>
|
||||
public string Manufacturer { get; private set; }
|
||||
public string Manufacturer { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Product name, or null if not available
|
||||
/// </summary>
|
||||
public string Product { get; private set; }
|
||||
public string Product { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Device serial number, or null if not available
|
||||
/// </summary>
|
||||
public string SerialNumber { get; private set; }
|
||||
|
||||
public string SerialNumber { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Friendly device name, or path name when no
|
||||
@@ -54,13 +53,21 @@ namespace MadWizard.WinUSBNet
|
||||
get
|
||||
{
|
||||
if (Manufacturer != null && Product != null)
|
||||
{
|
||||
return Product + " - " + Manufacturer;
|
||||
}
|
||||
else if (Product != null)
|
||||
{
|
||||
return Product;
|
||||
}
|
||||
else if (SerialNumber != null)
|
||||
{
|
||||
return SerialNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PathName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +79,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte ClassValue
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,7 +87,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte SubClass
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,7 +95,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte Protocol
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,7 +105,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBBaseClass BaseClass
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
internal USBDeviceDescriptor(string path, API.USB_DEVICE_DESCRIPTOR deviceDesc, string manufacturer, string product, string serialNumber)
|
||||
@@ -113,7 +116,6 @@ namespace MadWizard.WinUSBNet
|
||||
Product = product;
|
||||
SerialNumber = serialNumber;
|
||||
|
||||
|
||||
ClassValue = deviceDesc.bDeviceClass;
|
||||
SubClass = deviceDesc.bDeviceSubClass;
|
||||
Protocol = deviceDesc.bDeviceProtocol;
|
||||
@@ -123,11 +125,8 @@ namespace MadWizard.WinUSBNet
|
||||
BaseClass = USBBaseClass.Unknown;
|
||||
if (Enum.IsDefined(typeof(USBBaseClass), (int)deviceDesc.bDeviceClass))
|
||||
{
|
||||
BaseClass = (USBBaseClass)(int)deviceDesc.bDeviceClass;
|
||||
BaseClass = (USBBaseClass)deviceDesc.bDeviceClass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,6 +87,5 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
_details = details;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBPipeCollection Pipes
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -29,7 +28,6 @@ namespace MadWizard.WinUSBNet
|
||||
public int Number
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,7 +36,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBDevice Device
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,7 +44,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBPipe InPipe
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -56,7 +52,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBPipe OutPipe
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,7 +62,6 @@ namespace MadWizard.WinUSBNet
|
||||
public USBBaseClass BaseClass
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,7 +72,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte ClassValue
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -87,7 +80,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte SubClass
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -96,7 +88,6 @@ namespace MadWizard.WinUSBNet
|
||||
public byte Protocol
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// Zero based interface index in WinUSB.
|
||||
@@ -106,7 +97,6 @@ namespace MadWizard.WinUSBNet
|
||||
internal int InterfaceIndex
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
internal USBInterface(USBDevice device, int interfaceIndex, API.USB_INTERFACE_DESCRIPTOR rawDesc, USBPipeCollection pipes)
|
||||
@@ -124,10 +114,9 @@ namespace MadWizard.WinUSBNet
|
||||
BaseClass = USBBaseClass.Unknown;
|
||||
if (Enum.IsDefined(typeof(USBBaseClass), (int)rawDesc.bInterfaceClass))
|
||||
{
|
||||
BaseClass = (USBBaseClass)(int)rawDesc.bInterfaceClass;
|
||||
BaseClass = (USBBaseClass)rawDesc.bInterfaceClass;
|
||||
}
|
||||
|
||||
|
||||
Device = device;
|
||||
Pipes = pipes;
|
||||
|
||||
@@ -139,12 +128,15 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
// If first in or out pipe, set InPipe and OutPipe
|
||||
if (pipe.IsIn && InPipe == null)
|
||||
{
|
||||
InPipe = pipe;
|
||||
}
|
||||
|
||||
if (pipe.IsOut && OutPipe == null)
|
||||
{
|
||||
OutPipe = pipe;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace MadWizard.WinUSBNet
|
||||
/// </summary>
|
||||
public class USBInterfaceCollection : IEnumerable<USBInterface>
|
||||
{
|
||||
private USBInterface[] _interfaces;
|
||||
private readonly USBInterface[] _interfaces;
|
||||
|
||||
internal USBInterfaceCollection(USBInterface[] interfaces)
|
||||
{
|
||||
@@ -26,7 +26,7 @@ namespace MadWizard.WinUSBNet
|
||||
private class USBInterfaceEnumerator : IEnumerator<USBInterface>
|
||||
{
|
||||
private int _index;
|
||||
private USBInterface[] _interfaces;
|
||||
private readonly USBInterface[] _interfaces;
|
||||
|
||||
public USBInterfaceEnumerator(USBInterface[] interfaces)
|
||||
{
|
||||
@@ -44,7 +44,6 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
return _interfaces[_index];
|
||||
}
|
||||
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
@@ -59,7 +58,6 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
@@ -81,7 +79,7 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds the first interface with that matches the device class
|
||||
/// Finds the first interface with that matches the device class
|
||||
/// given by the <paramref name="interfaceClass"/> parameter.
|
||||
/// </summary>
|
||||
/// <param name="interfaceClass">The device class the interface should match</param>
|
||||
@@ -93,26 +91,30 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
USBInterface iface = _interfaces[i];
|
||||
if (iface.BaseClass == interfaceClass)
|
||||
{
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all interfaces matching the device class given by the
|
||||
/// Finds all interfaces matching the device class given by the
|
||||
/// <paramref name="interfaceClass"/> parameter.
|
||||
/// </summary>
|
||||
/// <param name="interfaceClass">The device class the interface should match</param>
|
||||
/// <returns>An array of USBInterface objects matching the device class, or an empty
|
||||
/// <returns>An array of USBInterface objects matching the device class, or an empty
|
||||
/// array if no interface matches.</returns>
|
||||
public USBInterface[] FindAll(USBBaseClass interfaceClass)
|
||||
{
|
||||
List<USBInterface> matchingInterfaces = new List<USBInterface>();
|
||||
List<USBInterface> matchingInterfaces = new();
|
||||
for (int i = 0; i < _interfaces.Length; i++)
|
||||
{
|
||||
USBInterface iface = _interfaces[i];
|
||||
if (iface.BaseClass == interfaceClass)
|
||||
{
|
||||
matchingInterfaces.Add(iface);
|
||||
}
|
||||
}
|
||||
return matchingInterfaces.ToArray();
|
||||
}
|
||||
@@ -141,7 +143,9 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
USBInterface iface = _interfaces[i];
|
||||
if (iface.Number == interfaceNumber)
|
||||
{
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
throw new IndexOutOfRangeException(string.Format("No interface with number {0} exists.", interfaceNumber));
|
||||
}
|
||||
|
||||
+15
-11
@@ -66,15 +66,15 @@ namespace MadWizard.WinUSBNet
|
||||
/// </summary>
|
||||
public class USBNotifier : IDisposable
|
||||
{
|
||||
private DeviceNotifyHook _hook;
|
||||
private readonly DeviceNotifyHook _hook;
|
||||
private Guid _guid;
|
||||
private WPinternals.AsyncAutoResetEvent NodeChangeEvent = new WPinternals.AsyncAutoResetEvent(false);
|
||||
private readonly WPinternals.AsyncAutoResetEvent NodeChangeEvent = new(false);
|
||||
|
||||
/// <summary>
|
||||
/// Event triggered when a new USB device that matches the USBNotifier's GUID is connected
|
||||
/// </summary>
|
||||
private event USBEventHandler _Arrival;
|
||||
public event USBEventHandler Arrival
|
||||
private event EventHandler<USBEvent> _Arrival;
|
||||
public event EventHandler<USBEvent> Arrival
|
||||
{
|
||||
// Heathcliff74 - Also notify currently connected USB devices
|
||||
add
|
||||
@@ -83,7 +83,9 @@ namespace MadWizard.WinUSBNet
|
||||
_Arrival += value;
|
||||
USBDeviceInfo[] Devices = USBDevice.GetDevices(Guid);
|
||||
foreach (USBDeviceInfo Device in Devices)
|
||||
{
|
||||
_Arrival(this, new USBEvent(USBEventType.DeviceArrival, Guid, Device.DevicePath));
|
||||
}
|
||||
}
|
||||
remove
|
||||
{
|
||||
@@ -94,7 +96,7 @@ namespace MadWizard.WinUSBNet
|
||||
/// <summary>
|
||||
/// Event triggered when a new USB device that matches the USBNotifier's GUID is disconnected
|
||||
/// </summary>
|
||||
public event USBEventHandler Removal;
|
||||
public event EventHandler<USBEvent> Removal;
|
||||
|
||||
/// <summary>
|
||||
/// The interface GUID of devices this USBNotifier will watch
|
||||
@@ -121,7 +123,6 @@ namespace MadWizard.WinUSBNet
|
||||
// Handled in other constructor
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new USBNotifier that will watch for events on
|
||||
/// devices matching the given interface GUID. A Windows Forms control
|
||||
@@ -142,8 +143,7 @@ namespace MadWizard.WinUSBNet
|
||||
/// <param name="devicePath">Device pathname of the device that has been connected</param>
|
||||
protected void OnArrival(string devicePath)
|
||||
{
|
||||
if (_Arrival != null)
|
||||
_Arrival(this, new USBEvent(USBEventType.DeviceArrival, _guid, devicePath));
|
||||
_Arrival?.Invoke(this, new USBEvent(USBEventType.DeviceArrival, _guid, devicePath));
|
||||
}
|
||||
/// <summary>
|
||||
/// Triggers the removal event
|
||||
@@ -151,14 +151,15 @@ namespace MadWizard.WinUSBNet
|
||||
/// <param name="devicePath">Device pathname of the device that has been connected</param>
|
||||
protected void OnRemoval(string devicePath)
|
||||
{
|
||||
if (Removal != null)
|
||||
Removal(this, new USBEvent(USBEventType.DeviceRemoval, _guid, devicePath));
|
||||
Removal?.Invoke(this, new USBEvent(USBEventType.DeviceRemoval, _guid, devicePath));
|
||||
}
|
||||
|
||||
internal int HandleDeviceChange(int msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (msg != API.DeviceManagement.WM_DEVICECHANGE)
|
||||
{
|
||||
throw new USBException("Invalid device change message."); // should not happen
|
||||
}
|
||||
|
||||
//switch ((int)wParam)
|
||||
//{
|
||||
@@ -183,14 +184,18 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
string devName = API.DeviceManagement.GetNotifyMessageDeviceName(lParam, _guid);
|
||||
if (devName != null)
|
||||
{
|
||||
OnArrival(devName);
|
||||
}
|
||||
}
|
||||
|
||||
if ((int)wParam == API.DeviceManagement.DBT_DEVICEREMOVECOMPLETE)
|
||||
{
|
||||
string devName = API.DeviceManagement.GetNotifyMessageDeviceName(lParam, _guid);
|
||||
if (devName != null)
|
||||
{
|
||||
OnRemoval(devName);
|
||||
}
|
||||
}
|
||||
|
||||
if ((int)wParam == API.DeviceManagement.DBT_DEVNODES_CHANGED)
|
||||
@@ -232,6 +237,5 @@ namespace MadWizard.WinUSBNet
|
||||
_hook.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+65
-37
@@ -17,7 +17,6 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
private API.WINUSB_PIPE_INFORMATION _pipeInfo;
|
||||
private USBInterface _interface = null;
|
||||
private USBDevice _device;
|
||||
private USBPipePolicy _policy;
|
||||
|
||||
private byte[] LastWritten = null;
|
||||
@@ -36,13 +35,7 @@ namespace MadWizard.WinUSBNet
|
||||
/// <summary>
|
||||
/// The USBDevice this pipe is associated with
|
||||
/// </summary>
|
||||
public USBDevice Device
|
||||
{
|
||||
get
|
||||
{
|
||||
return _device;
|
||||
}
|
||||
}
|
||||
public USBDevice Device { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum packet size for transfers on this endpoint
|
||||
@@ -122,9 +115,7 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
try
|
||||
{
|
||||
uint bytesRead;
|
||||
|
||||
_device.InternalDevice.ReadPipe(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, out bytesRead);
|
||||
Device.InternalDevice.ReadPipe(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, out uint bytesRead);
|
||||
|
||||
return (int)bytesRead;
|
||||
}
|
||||
@@ -139,30 +130,44 @@ namespace MadWizard.WinUSBNet
|
||||
private void CheckReadParams(byte[] buffer, int offset, int length)
|
||||
{
|
||||
if (!IsIn)
|
||||
{
|
||||
// throw new ArgumentOutOfRangeException("Offset of data to read is outside the buffer boundaries.");
|
||||
LogAndThrowException(new ArgumentOutOfRangeException("Offset of data to read is outside the buffer boundaries."));
|
||||
}
|
||||
|
||||
int bufferLength = buffer.Length;
|
||||
if (offset < 0 || offset >= bufferLength)
|
||||
{
|
||||
// throw new ArgumentOutOfRangeException(nameof(offset), "Offset of data to read is outside the buffer boundaries.");
|
||||
LogAndThrowException(new ArgumentOutOfRangeException("Offset of data to read is outside the buffer boundaries."));
|
||||
}
|
||||
|
||||
if (length < 0 || (offset + length) > bufferLength)
|
||||
{
|
||||
// throw new ArgumentOutOfRangeException(nameof(length), "Length of data to read is outside the buffer boundaries.");
|
||||
LogAndThrowException(new ArgumentOutOfRangeException("Length of data to read is outside the buffer boundaries."));
|
||||
}
|
||||
}
|
||||
private void CheckWriteParams(byte[] buffer, int offset, int length)
|
||||
{
|
||||
if (!IsOut)
|
||||
{
|
||||
//throw new NotSupportedException("Cannot write to a pipe with IN direction.");
|
||||
LogAndThrowException(new NotSupportedException("Cannot write to a pipe with IN direction."));
|
||||
}
|
||||
|
||||
int bufferLength = buffer.Length;
|
||||
if (offset < 0 || offset >= bufferLength)
|
||||
{
|
||||
// throw new ArgumentOutOfRangeException(nameof(offset), "Offset of data to write is outside the buffer boundaries.");
|
||||
LogAndThrowException(new ArgumentOutOfRangeException("Offset of data to write is outside the buffer boundaries."));
|
||||
}
|
||||
|
||||
if (length < 0 || (offset + length) > bufferLength)
|
||||
{
|
||||
// throw new ArgumentOutOfRangeException(nameof(length), "Length of data to write is outside the buffer boundaries.");
|
||||
LogAndThrowException(new ArgumentOutOfRangeException("Length of data to write is outside the buffer boundaries."));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Initiates an asynchronous read operation on the pipe. </summary>
|
||||
@@ -182,10 +187,10 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
CheckReadParams(buffer, offset, length);
|
||||
|
||||
USBAsyncResult result = new USBAsyncResult(userCallback, stateObject);
|
||||
USBAsyncResult result = new(userCallback, stateObject);
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.ReadPipeOverlapped(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, result);
|
||||
Device.InternalDevice.ReadPipeOverlapped(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, result);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
@@ -195,8 +200,7 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (result != null)
|
||||
result.Dispose();
|
||||
result?.Dispose();
|
||||
// throw;
|
||||
LogException(e);
|
||||
throw;
|
||||
@@ -218,22 +222,31 @@ namespace MadWizard.WinUSBNet
|
||||
public int EndRead(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult == null)
|
||||
{
|
||||
// throw new NullReferenceException("asyncResult cannot be null");
|
||||
LogAndThrowException(new NullReferenceException("asyncResult cannot be null"));
|
||||
}
|
||||
|
||||
if (!(asyncResult is USBAsyncResult))
|
||||
{
|
||||
// throw new ArgumentException("AsyncResult object was not created by calling BeginRead on this class.");
|
||||
LogAndThrowException(new ArgumentException("AsyncResult object was not created by calling BeginRead on this class."));
|
||||
}
|
||||
|
||||
// todo: check duplicate end reads?
|
||||
USBAsyncResult result = (USBAsyncResult)asyncResult;
|
||||
try
|
||||
{
|
||||
if (!result.IsCompleted)
|
||||
{
|
||||
result.AsyncWaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
if (result.Error != null)
|
||||
{
|
||||
// throw new USBException("Asynchronous read from pipe has failed.", result.Error);
|
||||
LogAndThrowException(new USBException("Asynchronous read from pipe has failed.", result.Error));
|
||||
}
|
||||
|
||||
return result.BytesTransfered;
|
||||
}
|
||||
@@ -241,7 +254,6 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
result.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -267,12 +279,12 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.WritePipe(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length);
|
||||
Device.InternalDevice.WritePipe(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
byte[] SubBuffer = new byte[(length < 16 ? length : 16)];
|
||||
Array.Copy(buffer, offset, SubBuffer, 0, (length < 16 ? length : 16));
|
||||
byte[] SubBuffer = new byte[length < 16 ? length : 16];
|
||||
Array.Copy(buffer, offset, SubBuffer, 0, length < 16 ? length : 16);
|
||||
// throw new USBException("Failed to write to pipe: " + WPinternals.Converter.ConvertHexToString(SubBuffer, ""), e);
|
||||
LogAndThrowException(new USBException("Failed to write to pipe: " + WPinternals.Converter.ConvertHexToString(SubBuffer, ""), e));
|
||||
}
|
||||
@@ -297,25 +309,23 @@ namespace MadWizard.WinUSBNet
|
||||
|
||||
LogLastWrite(buffer, offset, length);
|
||||
|
||||
USBAsyncResult result = new USBAsyncResult(userCallback, stateObject);
|
||||
USBAsyncResult result = new(userCallback, stateObject);
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.WriteOverlapped(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, result);
|
||||
Device.InternalDevice.WriteOverlapped(Interface.InterfaceIndex, _pipeInfo.PipeId, buffer, offset, length, result);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
if (result != null)
|
||||
result.Dispose();
|
||||
result?.Dispose();
|
||||
|
||||
byte[] SubBuffer = new byte[(length < 16 ? length : 16)];
|
||||
Array.Copy(buffer, offset, SubBuffer, 0, (length < 16 ? length : 16));
|
||||
byte[] SubBuffer = new byte[length < 16 ? length : 16];
|
||||
Array.Copy(buffer, offset, SubBuffer, 0, length < 16 ? length : 16);
|
||||
// throw new USBException("Failed to write to pipe: " + WPinternals.Converter.ConvertHexToString(SubBuffer, ""), e);
|
||||
LogAndThrowException(new USBException("Failed to write to pipe: " + WPinternals.Converter.ConvertHexToString(SubBuffer, ""), e));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (result != null)
|
||||
result.Dispose();
|
||||
result?.Dispose();
|
||||
// throw;
|
||||
LogException(e);
|
||||
throw;
|
||||
@@ -337,11 +347,16 @@ namespace MadWizard.WinUSBNet
|
||||
public void EndWrite(IAsyncResult asyncResult)
|
||||
{
|
||||
if (asyncResult == null)
|
||||
{
|
||||
// throw new NullReferenceException("asyncResult cannot be null");
|
||||
LogAndThrowException(new NullReferenceException("asyncResult cannot be null"));
|
||||
}
|
||||
|
||||
if (!(asyncResult is USBAsyncResult))
|
||||
{
|
||||
// throw new ArgumentException("AsyncResult object was not created by calling BeginWrite on this class.");
|
||||
LogAndThrowException(new ArgumentException("AsyncResult object was not created by calling BeginWrite on this class."));
|
||||
}
|
||||
|
||||
USBAsyncResult result = (USBAsyncResult)asyncResult;
|
||||
try
|
||||
@@ -349,11 +364,15 @@ namespace MadWizard.WinUSBNet
|
||||
// todo: check duplicate end writes?
|
||||
|
||||
if (!result.IsCompleted)
|
||||
{
|
||||
result.AsyncWaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
if (result.Error != null)
|
||||
{
|
||||
// throw new USBException("Asynchronous write to pipe has failed.", result.Error);
|
||||
LogAndThrowException(new USBException("Asynchronous write to pipe has failed.", result.Error));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -368,7 +387,7 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.AbortPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
Device.InternalDevice.AbortPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
@@ -384,7 +403,7 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.ResetPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
Device.InternalDevice.ResetPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
@@ -399,10 +418,13 @@ namespace MadWizard.WinUSBNet
|
||||
public void Flush()
|
||||
{
|
||||
if (!IsIn)
|
||||
{
|
||||
throw new NotSupportedException("Flush is only supported on IN direction pipes");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_device.InternalDevice.FlushPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
Device.InternalDevice.FlushPipe(Interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
}
|
||||
catch (API.APIException e)
|
||||
{
|
||||
@@ -414,7 +436,7 @@ namespace MadWizard.WinUSBNet
|
||||
internal USBPipe(USBDevice device, API.WINUSB_PIPE_INFORMATION pipeInfo)
|
||||
{
|
||||
_pipeInfo = pipeInfo;
|
||||
_device = device;
|
||||
Device = device;
|
||||
|
||||
// Policy is not set until interface is attached
|
||||
_policy = null;
|
||||
@@ -425,24 +447,31 @@ namespace MadWizard.WinUSBNet
|
||||
_interface = usbInterface;
|
||||
|
||||
// Initialize policy now that interface is set (policy requires interface)
|
||||
_policy = new USBPipePolicy(_device, _interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
_policy = new USBPipePolicy(Device, _interface.InterfaceIndex, _pipeInfo.PipeId);
|
||||
}
|
||||
|
||||
private void LogException(Exception Ex)
|
||||
{
|
||||
WPinternals.LogFile.Log("Error on USB port!", WPinternals.LogType.FileOnly);
|
||||
WPinternals.LogFile.Log("Device: " + _device.Descriptor.FullName, WPinternals.LogType.FileOnly);
|
||||
WPinternals.LogFile.Log("Device: " + Device.Descriptor.FullName, WPinternals.LogType.FileOnly);
|
||||
|
||||
if (IsIn)
|
||||
LastWritten = _device.OutputPipe.LastWritten;
|
||||
{
|
||||
LastWritten = Device.OutputPipe.LastWritten;
|
||||
}
|
||||
|
||||
if ((LastWritten == null) && (Ex is USBException) && (Ex.InnerException is MadWizard.WinUSBNet.API.APIException) &&
|
||||
(((MadWizard.WinUSBNet.API.APIException)Ex.InnerException).InnerException is System.ComponentModel.Win32Exception) &&
|
||||
if ((LastWritten == null) && (Ex is USBException) && (Ex.InnerException is API.APIException) &&
|
||||
(((API.APIException)Ex.InnerException).InnerException is System.ComponentModel.Win32Exception) &&
|
||||
(((System.ComponentModel.Win32Exception)Ex.InnerException.InnerException).NativeErrorCode == 0X1F))
|
||||
{
|
||||
WPinternals.LogFile.Log("Failed to communicate on new USB connection", WPinternals.LogType.FileAndConsole);
|
||||
}
|
||||
|
||||
if (LastWritten != null)
|
||||
{
|
||||
WPinternals.LogFile.Log("Last written: " + WPinternals.Converter.ConvertHexToString(LastWritten, ""), WPinternals.LogType.FileOnly);
|
||||
}
|
||||
|
||||
WPinternals.LogFile.LogException(Ex, WPinternals.LogType.FileOnly);
|
||||
}
|
||||
|
||||
@@ -457,5 +486,4 @@ namespace MadWizard.WinUSBNet
|
||||
System.Buffer.BlockCopy(Buffer, Offset, LastWritten, 0, LastWritten.Length);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ namespace MadWizard.WinUSBNet
|
||||
/// </summary>
|
||||
public class USBPipeCollection : IEnumerable<USBPipe>
|
||||
{
|
||||
private Dictionary<byte, USBPipe> _pipes;
|
||||
private readonly Dictionary<byte, USBPipe> _pipes;
|
||||
|
||||
internal USBPipeCollection(USBPipe[] pipes)
|
||||
{
|
||||
@@ -24,13 +24,16 @@ namespace MadWizard.WinUSBNet
|
||||
foreach (USBPipe pipe in pipes)
|
||||
{
|
||||
if (_pipes.ContainsKey(pipe.Address))
|
||||
{
|
||||
throw new USBException("Duplicate pipe address in endpoint.");
|
||||
}
|
||||
|
||||
_pipes[pipe.Address] = pipe;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the pipe from the collection with the given pipe address
|
||||
/// Returns the pipe from the collection with the given pipe address
|
||||
/// </summary>
|
||||
/// <param name="pipeAddress">Address of the pipe to return</param>
|
||||
/// <returns>The pipe with the given pipe address</returns>
|
||||
@@ -40,9 +43,11 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
get
|
||||
{
|
||||
USBPipe pipe;
|
||||
if (!_pipes.TryGetValue(pipeAddress, out pipe))
|
||||
if (!_pipes.TryGetValue(pipeAddress, out USBPipe pipe))
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return pipe;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +55,7 @@ namespace MadWizard.WinUSBNet
|
||||
private class UsbPipeEnumerator : IEnumerator<USBPipe>
|
||||
{
|
||||
private int _index;
|
||||
private USBPipe[] _pipes;
|
||||
private readonly USBPipe[] _pipes;
|
||||
|
||||
public UsbPipeEnumerator(USBPipe[] pipes)
|
||||
{
|
||||
@@ -68,7 +73,6 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
return _pipes[_index];
|
||||
}
|
||||
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
@@ -83,7 +87,6 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object IEnumerator.Current
|
||||
{
|
||||
get
|
||||
@@ -102,7 +105,6 @@ namespace MadWizard.WinUSBNet
|
||||
{
|
||||
_index = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private USBPipe[] GetPipeList()
|
||||
|
||||
+19
-17
@@ -9,16 +9,14 @@ using System;
|
||||
|
||||
namespace MadWizard.WinUSBNet
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Describes the policy for a specific USB pipe
|
||||
/// </summary>
|
||||
public class USBPipePolicy
|
||||
{
|
||||
|
||||
private byte _pipeID;
|
||||
private int _interfaceIndex;
|
||||
private USBDevice _device;
|
||||
private readonly byte _pipeID;
|
||||
private readonly int _interfaceIndex;
|
||||
private readonly USBDevice _device;
|
||||
|
||||
internal USBPipePolicy(USBDevice device, int interfaceIndex, byte pipeID)
|
||||
{
|
||||
@@ -27,13 +25,13 @@ namespace MadWizard.WinUSBNet
|
||||
_device = device;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void RequireDirectionOut()
|
||||
{
|
||||
// Some policy types only apply specifically to OUT direction pipes
|
||||
if ((_pipeID & 0x80) != 0)
|
||||
{
|
||||
throw new NotSupportedException("This policy type is only allowed on OUT direction pipes.");
|
||||
}
|
||||
}
|
||||
|
||||
private void RequireDirectionIn()
|
||||
@@ -41,11 +39,13 @@ namespace MadWizard.WinUSBNet
|
||||
// Some policy types only apply specifically to IN direction pipes
|
||||
// This function checks for this.
|
||||
if ((_pipeID & 0x80) == 0)
|
||||
{
|
||||
throw new NotSupportedException("This policy type is only allowed on IN direction pipes.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When false, read requests fail when the device returns more data than requested. When true, extra data is
|
||||
/// When false, read requests fail when the device returns more data than requested. When true, extra data is
|
||||
/// saved and returned on the next read. Default value is true. Only available on IN direction pipes.
|
||||
/// </summary>
|
||||
/// <seealso href="http://msdn.microsoft.com/en-us/library/aa476439.aspx">WinUSB_GetPipePolicy for a more detailed description</seealso>
|
||||
@@ -90,7 +90,7 @@ namespace MadWizard.WinUSBNet
|
||||
get
|
||||
{
|
||||
RequireDirectionIn();
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.AUTO_FLUSH); ;
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.AUTO_FLUSH);
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -108,7 +108,7 @@ namespace MadWizard.WinUSBNet
|
||||
get
|
||||
{
|
||||
RequireDirectionIn();
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.IGNORE_SHORT_PACKETS); ;
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.IGNORE_SHORT_PACKETS);
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -131,23 +131,26 @@ namespace MadWizard.WinUSBNet
|
||||
set
|
||||
{
|
||||
if (value < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Pipe transfer timeout cannot be negative.");
|
||||
}
|
||||
|
||||
_device.InternalDevice.SetPipePolicy(_interfaceIndex, _pipeID, API.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, (uint)value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When true, read and write operations to the pipe must have a buffer length that is a multiple of the maximum endpoint packet size,
|
||||
/// When true, read and write operations to the pipe must have a buffer length that is a multiple of the maximum endpoint packet size,
|
||||
/// and the length must be less than the maximum transfer size. With these conditions met, data is sent directly to the USB driver stack,
|
||||
/// bypassing the queuing and error handling of WinUSB.
|
||||
/// Default value is false.
|
||||
/// bypassing the queuing and error handling of WinUSB.
|
||||
/// Default value is false.
|
||||
/// </summary>
|
||||
/// <seealso href="http://msdn.microsoft.com/en-us/library/aa476439.aspx">WinUSB_GetPipePolicy for a more detailed description</seealso>
|
||||
public bool RawIO
|
||||
{
|
||||
get
|
||||
{
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.RAW_IO); ;
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.RAW_IO);
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -156,7 +159,7 @@ namespace MadWizard.WinUSBNet
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When true, every write request that is a multiple of the maximum packet size for the endpoint is terminated with a zero-length packet.
|
||||
/// When true, every write request that is a multiple of the maximum packet size for the endpoint is terminated with a zero-length packet.
|
||||
/// Default value is false. Only available on OUT direction pipes.
|
||||
/// </summary>
|
||||
/// <seealso href="http://msdn.microsoft.com/en-us/library/aa476439.aspx">WinUSB_GetPipePolicy for a more detailed description</seealso>
|
||||
@@ -165,7 +168,7 @@ namespace MadWizard.WinUSBNet
|
||||
get
|
||||
{
|
||||
RequireDirectionOut();
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.SHORT_PACKET_TERMINATE); ;
|
||||
return _device.InternalDevice.GetPipePolicyBool(_interfaceIndex, _pipeID, API.POLICY_TYPE.SHORT_PACKET_TERMINATE);
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -173,6 +176,5 @@ namespace MadWizard.WinUSBNet
|
||||
_device.InternalDevice.SetPipePolicy(_interfaceIndex, _pipeID, API.POLICY_TYPE.SHORT_PACKET_TERMINATE, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user