Project Maintenance

This commit is contained in:
Gustave Monce
2021-08-09 20:21:09 +02:00
parent 9865ef7f79
commit 847ce0506d
411 changed files with 5922 additions and 54941 deletions
-4
View File
@@ -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));
}
}
}
+50 -37
View File
@@ -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");
}
}
}
}
+7 -8
View File
@@ -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);
+1 -3
View File
@@ -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);
}
}
+77 -37
View File
@@ -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;
}
}
+8 -14
View File
@@ -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;
}
}
+19 -12
View File
@@ -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 { }
}
}
}
}
-1
View File
@@ -73,5 +73,4 @@ namespace MadWizard.WinUSBNet
/// <summary>Vendor specific base class (0xFF)</summary>
VendorSpecific = 0xFF,
};
}
+11 -17
View File
@@ -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
View File
@@ -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);
}
}
}
}
+15 -16
View File
@@ -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;
}
}
}
}
-1
View File
@@ -87,6 +87,5 @@ namespace MadWizard.WinUSBNet
{
_details = details;
}
}
}
+6 -14
View File
@@ -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;
}
}
}
}
}
+12 -8
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
}
}
+10 -8
View File
@@ -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
View File
@@ -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);
}
}
}
}