| |
// / This HTML file was produced by the ProjectPublisher WebService, By Asaf Shelly / //
// / WebService URL is: http://Services.AsyncOp.com/ProjectPublisher/ProjectPublisherWSvc.asmx / //
// / Learn more and find the source code here: http://AsyncOp.com / //
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Collections;
namespace WinUSBDeviceAPI
{
public interface WinUSBDeviceAPINotification
{
void OnDeviceAttach();
void OnDeviceDetach();
void OnReadCompletion(int ep, byte[] buffer, int lastErrorCode, object userContext);
void OnWriteCompletion(int ep, int byteCount, int lastErrorCode, object userContext);
}
public interface WinUSBNotifyDevice
{
void OnDeviceAttach();
void OnDeviceDetach();
}
public delegate void ReadCompletionDelegate(byte[] buffer, int lastErrorCode, object userContext);
public delegate void WriteCompletionDelegate(int byteCount, int lastErrorCode, object userContext);
public class WinUsbDeviceApi
{
private IntPtr hWinUsbDevice = IntPtr.Zero;
private SafeFileHandle hDeviceFile = null;
protected Guid DeviceGuid = Guid.Empty;
string DevicePath = null;
int InterfaceNumber = -1;
public WinUsbDeviceApi(Guid deviceGuid)
{
DeviceGuid = deviceGuid;
}
public WinUsbDeviceApi(string deviceGuidString)
{
DeviceGuid = new Guid(deviceGuidString);
}
public WinUsbDeviceApi(Guid deviceGuid, int interfaceNumber)
{
if (Guid.Empty == deviceGuid) throw (new Exception("null deviceGuid"));
DeviceGuid = deviceGuid;
InterfaceNumber = interfaceNumber;
}
protected void CloseWinUSB()
{
if (IntPtr.Zero == hWinUsbDevice) return;
WinUsbAPI.WinUsb_Free(hWinUsbDevice); hWinUsbDevice = IntPtr.Zero;
}
protected void CloseHandle()
{
if (null == hDeviceFile) return;
if (IntPtr.Zero != hWinUsbDevice) CloseWinUSB();
if ((hDeviceFile.IsInvalid) || (hDeviceFile.IsClosed)) return;
hDeviceFile.Close(); hDeviceFile = null;
}
public bool IsEndpointDirIn(int epNumber)
{
return ((epNumber & 0X80) == 0X80);
}
protected bool SetPipePolicy(byte pipeId, WinUsbAPI.POLICY_TYPE policyType, bool value)
{
byte val = Convert.ToByte(value);
return (WinUsbAPI.WinUsb_SetPipePolicy(hWinUsbDevice, pipeId, (uint)policyType, 1, ref val));
}
protected bool SetPipePolicy(byte pipeId, WinUsbAPI.POLICY_TYPE policyType, byte value)
{
return (WinUsbAPI.WinUsb_SetPipePolicy(hWinUsbDevice, pipeId, (uint)policyType, 1, ref value));
}
protected bool SetPipePolicy(byte pipeId, WinUsbAPI.POLICY_TYPE policyType, uint value)
{
return (WinUsbAPI.WinUsb_SetPipePolicyI(hWinUsbDevice, pipeId, (uint)policyType, 4, ref value));
}
protected WinUsbAPI.WINUSB_PIPE_INFORMATION[] Pipes = null;
protected bool InitPipes(WinUsbAPI.USB_INTERFACE_DESCRIPTOR ifaceDescriptor)
{
Pipes = new WinUsbAPI.WINUSB_PIPE_INFORMATION[ifaceDescriptor.bNumEndpoints];
Array.Clear(Pipes, 0, Pipes.Length);
for (byte epIndex = 0; epIndex <= ifaceDescriptor.bNumEndpoints - 1; epIndex++)
{
if (WinUsbAPI.WinUsb_QueryPipe(hWinUsbDevice, 0, epIndex, ref Pipes[epIndex]))
{
if (WinUsbAPI.USBD_PIPE_TYPE.UsbdPipeTypeBulk == Pipes[epIndex].PipeType)
{
if (IsEndpointDirIn(Pipes[epIndex].PipeId))
{
SetPipePolicy(Pipes[epIndex].PipeId, WinUsbAPI.POLICY_TYPE.IGNORE_SHORT_PACKETS, false);
SetPipePolicy(Pipes[epIndex].PipeId, WinUsbAPI.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, 1000);
}
}
}
}
return (true);
}
protected int FindPipeIndex(byte ep)
{
if (null == Pipes) return (-1);
ep = (byte)(ep & 0x0F);
for (int index = 0; index < Pipes.Length; index++)
{
if (((Pipes[index].PipeId) & 0x0F) == ep) return (index);
}
return (-1);
}
public bool SetPipeTimeout(byte ep, uint timeout)
{
int index = FindPipeIndex(ep);
if (-1 == index) return (false);
// Pipes[index].PipeId instead of ep to verify 0x82 instead of 0x02 for in pipes
return (SetPipePolicy(Pipes[index].PipeId, WinUsbAPI.POLICY_TYPE.PIPE_TRANSFER_TIMEOUT, timeout));
}
public bool SetPipeTimeoutInfinite(byte ep)
{
return (SetPipeTimeout(ep, 0));
}
Control DeviceNotifyTarget = null;
public bool Activate(Control deviceNotifyTarget)
{
WinUSBDeviceAPINotification host = deviceNotifyTarget as WinUSBDeviceAPINotification; // verify conversion
DeviceNotifyTarget = deviceNotifyTarget;
bool retval = RegisterDeviceNotification(DeviceNotifyTarget.Handle);
if (Open()) host.OnDeviceAttach();
return (retval);
}
public void Deactivate()
{
Close();
if (DeviceNotifyTarget != null) { DevMgmtAPI.UnregisterDeviceNotification(DeviceNotifyTarget.Handle); DeviceNotifyTarget = null; }
}
public bool Open()
{
if (hWinUsbDevice != IntPtr.Zero) return (true);
DevicePath = DevMgmtAPI.GetDevicePath(DeviceGuid);
if (null == DevicePath) return (false);
string devicePath = DevicePath;
if ((InterfaceNumber >= 0) && (InterfaceNumber < 9)) devicePath = devicePath + "MI_0" + InterfaceNumber.ToString();
hDeviceFile = FileIO.CreateFile(devicePath, 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 (hDeviceFile.IsInvalid) return (false);
if (!WinUsbAPI.WinUsb_Initialize(hDeviceFile, ref hWinUsbDevice)) { CloseHandle(); return (false); }
WinUsbAPI.USB_INTERFACE_DESCRIPTOR ifaceDescriptor = new WinUsbAPI.USB_INTERFACE_DESCRIPTOR(0);
if (!WinUsbAPI.WinUsb_QueryInterfaceSettings(hWinUsbDevice, 0, ref ifaceDescriptor)) { CloseWinUSB(); CloseHandle(); return (false); }
if (!InitPipes(ifaceDescriptor)) { CloseWinUSB(); CloseHandle(); return (false); }
return (true);
}
public void Close()
{
CloseWinUSB(); CloseHandle();
}
public uint ReadViaBulkTransfer(Byte pipeID, UInt32 bytesToRead, ref Byte[] buffer)
{
UInt32 bytesRead = 0;
//if (!(WinUsbAPI.WinUsb_ReadPipe(hWinUsbDevice, pipeID, buffer, bytesToRead, ref bytesRead, IntPtr.Zero))) return (0);
//System.Diagnostics.Debug.WriteLine("[WinUSB] ReadViaBulkTransfer: GetLastError = "+Marshal.GetLastWin32Error().ToString());
WinUsbAPI.WinUsb_ReadPipe(hWinUsbDevice, pipeID, buffer, bytesToRead, ref bytesRead, IntPtr.Zero);
System.Diagnostics.Debug.WriteLine("[WinUSB] ReadViaBulkTransfer: bytesRead = " + bytesRead.ToString() + " GetLastError = "+Marshal.GetLastWin32Error().ToString());
return (bytesRead);
}
public uint WriteViaBulkTransfer(Byte pipeID, ref Byte[] buffer, UInt32 bytesToWrite)
{
UInt32 bytesWritten = 0;
//if (!(WinUsbAPI.WinUsb_WritePipe(hWinUsbDevice, pipeID, buffer, bytesToWrite, ref bytesWritten, IntPtr.Zero))) return (0);
WinUsbAPI.WinUsb_WritePipe(hWinUsbDevice, pipeID, buffer, bytesToWrite, ref bytesWritten, IntPtr.Zero);
return (bytesWritten);
}
protected bool MatchDevice(Message msg)
{
int stringSize;
DevMgmtAPI.DEV_BROADCAST_DEVICEINTERFACE_1 devBroadcastDeviceInterface = new DevMgmtAPI.DEV_BROADCAST_DEVICEINTERFACE_1();
DevMgmtAPI.DEV_BROADCAST_HDR devBroadcastHeader = new DevMgmtAPI.DEV_BROADCAST_HDR();
Marshal.PtrToStructure(msg.LParam, devBroadcastHeader);
if (devBroadcastHeader.dbch_devicetype != DevMgmtAPI.DBT_DEVTYP_DEVICEINTERFACE) return (false);
stringSize = System.Convert.ToInt32((devBroadcastHeader.dbch_size - 32) / 2);
devBroadcastDeviceInterface.dbcc_name = new Char[stringSize + 1];
Marshal.PtrToStructure(msg.LParam, devBroadcastDeviceInterface);
String DeviceNameString = new String(devBroadcastDeviceInterface.dbcc_name, 0, stringSize);
//return(0==string.Compare(DeviceNameString,DevicePath,true));
return (DeviceNameString.Contains(DeviceGuid.ToString()));
}
public bool WndProc(ref Message msg)
{
WinUSBDeviceAPINotification host = DeviceNotifyTarget as WinUSBDeviceAPINotification;
if (msg.Msg == DevMgmtAPI.WM_DEVICECHANGE)
{
if ((msg.WParam.ToInt32() == DevMgmtAPI.DBT_DEVICEARRIVAL))
{
if (MatchDevice(msg))
{
Open();
if (host != null) host.OnDeviceAttach();
return (true);
}
else return (false);
}
else if ((msg.WParam.ToInt32() == DevMgmtAPI.DBT_DEVICEREMOVECOMPLETE))
{
if (MatchDevice(msg))
{
Close();
if (host != null) host.OnDeviceDetach();
return (true);
}
else return (false);
}
else return (false);
}
else return (false);
}
delegate void OnReadCompletionDelegate(int ep, byte[] buffer, int lastErrorCode, object userContext);
delegate void OnWriteCompletionDelegate(int ep, int byteCount, int lastErrorCode, object userContext);
IntPtr deviceNotificationHandle = IntPtr.Zero;
internal bool RegisterDeviceNotification(IntPtr formHandle)
{
DevMgmtAPI.DEV_BROADCAST_DEVICEINTERFACE devBroadcastDeviceInterface = new DevMgmtAPI.DEV_BROADCAST_DEVICEINTERFACE();
IntPtr devBroadcastDeviceInterfaceBuffer = IntPtr.Zero;
Int32 size = 0;
try
{
size = Marshal.SizeOf(devBroadcastDeviceInterface);
devBroadcastDeviceInterface.dbcc_size = size;
devBroadcastDeviceInterface.dbcc_devicetype = DevMgmtAPI.DBT_DEVTYP_DEVICEINTERFACE;
devBroadcastDeviceInterface.dbcc_reserved = 0;
devBroadcastDeviceInterface.dbcc_classguid = DeviceGuid;
devBroadcastDeviceInterfaceBuffer = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(devBroadcastDeviceInterface, devBroadcastDeviceInterfaceBuffer, true);
deviceNotificationHandle = DevMgmtAPI.RegisterDeviceNotification(formHandle, devBroadcastDeviceInterfaceBuffer, DevMgmtAPI.DEVICE_NOTIFY_WINDOW_HANDLE);
Marshal.PtrToStructure(devBroadcastDeviceInterfaceBuffer, devBroadcastDeviceInterface);
return (deviceNotificationHandle != IntPtr.Zero);
}
catch
{
if (deviceNotificationHandle != IntPtr.Zero) UnregisterDeviceNotification(deviceNotificationHandle);
throw;
}
finally
{
if (devBroadcastDeviceInterfaceBuffer != IntPtr.Zero)
{
Marshal.FreeHGlobal(devBroadcastDeviceInterfaceBuffer);
}
}
}
internal void UnregisterDeviceNotification(IntPtr deviceNotificationHandle)
{
DevMgmtAPI.UnregisterDeviceNotification(deviceNotificationHandle);
deviceNotificationHandle = IntPtr.Zero;
}
public int LastError
{
get
{
return (Marshal.GetLastWin32Error());
}
}
protected delegate void DeviceRWDelegate(ref Byte pipeID, ref Byte[] buffer, ref int byteCount, ref int lastError, ref object userContext);
public byte[] ReadBlocking(byte pipeID, int byteCount)
{
Byte[] buffer = new Byte[byteCount];
int lastError = -1;
DeviceRWDelegate reader = new DeviceRWDelegate(ReadBulk);
pipeID += (byte)0x80; // direction:in pipe
object userContext = null;
IAsyncResult async = reader.BeginInvoke(ref pipeID, ref buffer, ref byteCount, ref lastError, ref userContext, null, null);
async.AsyncWaitHandle.WaitOne(); // WinUSB sub system has timeout for each pipe
byte[] retval = ReadCompletion(reader, async, true);
async.AsyncWaitHandle.Close();
System.Diagnostics.Debug.WriteLine("[WinUSB] ReadBlocking: byteCount = " + retval.Length.ToString());
return (retval);
}
public void Read(Byte pipeID, int byteCount)
{
Read(pipeID, byteCount, null);
}
public void Read(Byte pipeID, int byteCount, object userContext)
{
Byte[] buffer = new Byte[byteCount];
int lastError = -1;
DeviceRWDelegate reader = new DeviceRWDelegate(ReadBulk);
pipeID += (byte)0x80; // direction:in pipe
IAsyncResult async = reader.BeginInvoke(ref pipeID, ref buffer, ref byteCount, ref lastError, ref userContext, new AsyncCallback(AsyncReadCompletion), reader);
}
void ReadBulk(ref Byte pipeID, ref Byte[] buffer, ref int byteCount, ref int lastError, ref object userContext)
{
byteCount = (int)ReadViaBulkTransfer(pipeID, (uint)buffer.Length, ref buffer);
lastError = Marshal.GetLastWin32Error();
}
void AsyncReadCompletion(IAsyncResult async)
{
ReadCompletion(async.AsyncState as DeviceRWDelegate, async, false);
}
byte[] ReadCompletion(DeviceRWDelegate reader, IAsyncResult async, bool blocking)
{
byte[] buffer = null;
int byteCount = 0;
int lastError = 0;
byte[] rcvBuffer = null;
object userContext = null;
byte ep = 0;
reader.EndInvoke(ref ep, ref buffer, ref byteCount, ref lastError, ref userContext, async);
System.Diagnostics.Debug.WriteLine("[WinUSB] ReadCompletion: byteCount = " + byteCount.ToString() + " / lastError = " + lastError.ToString());
if ((997 == lastError) || ((121 == lastError) && (0 != byteCount))) lastError = 0;
//if ((lastError != 0)&&(lastError != 997/*Pending*/)) rcvBuffer = new byte[0];
if (lastError != 0) rcvBuffer = new byte[0];
else if (byteCount < 1) { rcvBuffer = new byte[0]; lastError = -1; }
else
{
rcvBuffer = new byte[byteCount];
Array.Copy(buffer, rcvBuffer, rcvBuffer.Length); // assuming that byteCount is no more than buffer.Length
}
if (!blocking)
{
if (DeviceNotifyTarget != null) DeviceNotifyTarget.Invoke(new OnReadCompletionDelegate((DeviceNotifyTarget as WinUSBDeviceAPINotification).OnReadCompletion), new object[] { ep & 0x0F, rcvBuffer, lastError, userContext });
}
return (rcvBuffer);
}
public int WriteBlocking(Byte pipeID, byte[] buffer)
{
return (WriteBlocking(pipeID, buffer, buffer.Length));
}
public int WriteBlocking(byte pipeID, byte[] buffer, int byteCount)
{
int lastError = -1;
DeviceRWDelegate writer = new DeviceRWDelegate(WriteBulk);
object userContext = null;
IAsyncResult async = writer.BeginInvoke(ref pipeID, ref buffer, ref byteCount, ref lastError, ref userContext, null, null);
async.AsyncWaitHandle.WaitOne(); // WinUSB sub system has timeout for each pipe
int retval = WriteCompletion(writer, async, true);
async.AsyncWaitHandle.Close();
return (retval);
}
public void Write(Byte pipeID, byte[] buffer)
{
Write(pipeID, buffer, buffer.Length, null);
}
public void Write(Byte pipeID, byte[] buffer, object userContext)
{
Write(pipeID, buffer, buffer.Length, userContext);
}
public void Write(Byte pipeID, byte[] buffer, int byteCount)
{
Write(pipeID, buffer, byteCount, null);
}
public void Write(Byte pipeID, byte[] buffer, int byteCount, object userContext)
{
int lastError = -1;
DeviceRWDelegate writer = new DeviceRWDelegate(WriteBulk);
IAsyncResult async = writer.BeginInvoke(ref pipeID, ref buffer, ref byteCount, ref lastError, ref userContext, new AsyncCallback(AsyncWriteCompletion), writer);
}
void WriteBulk(ref Byte pipeID, ref Byte[] buffer, ref int byteCount, ref int lastError, ref object userContext)
{
byteCount = (int)WriteViaBulkTransfer(pipeID, ref buffer, (uint)buffer.Length);
lastError = Marshal.GetLastWin32Error();
}
void AsyncWriteCompletion(IAsyncResult async)
{
WriteCompletion(async.AsyncState as DeviceRWDelegate, async, false);
}
int WriteCompletion(DeviceRWDelegate writer, IAsyncResult async, bool blocking)
{
byte[] buffer = null;
int byteCount = 0;
int lastError = 0;
object userContext = null;
byte ep = 0;
writer.EndInvoke(ref ep, ref buffer, ref byteCount, ref lastError, ref userContext, async);
if (997 == lastError) lastError = 0;
if (lastError != 0) byteCount = 0;
if (!blocking)
{
if (DeviceNotifyTarget != null) DeviceNotifyTarget.Invoke(new OnWriteCompletionDelegate((DeviceNotifyTarget as WinUSBDeviceAPINotification).OnWriteCompletion), new object[] { ep, byteCount, lastError, userContext });
}
return (byteCount);
}
}
public class WinUsbAPI
{
internal const UInt32 DEVICE_SPEED = ((UInt32)(1));
internal const Byte USB_ENDPOINT_DIRECTION_MASK = ((Byte)(0X80));
public enum POLICY_TYPE
{
SHORT_PACKET_TERMINATE = 1,
AUTO_CLEAR_STALL,
PIPE_TRANSFER_TIMEOUT,
IGNORE_SHORT_PACKETS,
ALLOW_PARTIAL_READS,
AUTO_FLUSH,
RAW_IO,
}
internal enum USBD_PIPE_TYPE
{
UsbdPipeTypeControl,
UsbdPipeTypeIsochronous,
UsbdPipeTypeBulk,
UsbdPipeTypeInterrupt,
}
internal enum USB_DEVICE_SPEED
{
UsbLowSpeed = 1,
UsbFullSpeed,
UsbHighSpeed,
}
[StructLayout(LayoutKind.Sequential)]
internal struct USB_CONFIGURATION_DESCRIPTOR
{
internal Byte bLength;
internal Byte bDescriptorType;
internal ushort wTotalLength;
internal Byte bNumInterfaces;
internal Byte bConfigurationValue;
internal Byte iConfiguration;
internal Byte bmAttributes;
internal Byte MaxPower;
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_INTERFACE_DESCRIPTOR
{
internal Byte bLength;
internal Byte bDescriptorType;
internal Byte bInterfaceNumber;
internal Byte bAlternateSetting;
internal Byte bNumEndpoints;
internal Byte bInterfaceClass;
internal Byte bInterfaceSubClass;
internal Byte bInterfaceProtocol;
internal Byte iInterface;
public USB_INTERFACE_DESCRIPTOR(byte initVal)
{
bLength = initVal;
bDescriptorType = initVal;
bInterfaceNumber = initVal;
bAlternateSetting = initVal;
bNumEndpoints = initVal;
bInterfaceClass = initVal;
bInterfaceSubClass = initVal;
bInterfaceProtocol = initVal;
iInterface = initVal;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WINUSB_PIPE_INFORMATION
{
internal USBD_PIPE_TYPE PipeType;
internal Byte PipeId;
internal ushort MaximumPacketSize;
internal Byte Interval;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct WINUSB_SETUP_PACKET
{
internal Byte RequestType;
internal Byte Request;
internal ushort Value;
internal ushort Index;
internal ushort Length;
}
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_ControlTransfer(IntPtr InterfaceHandle, WINUSB_SETUP_PACKET SetupPacket, Byte[] Buffer, UInt32 BufferLength, ref UInt32 LengthTransferred, IntPtr Overlapped);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_Free(IntPtr InterfaceHandle);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_Initialize(SafeFileHandle DeviceHandle, ref IntPtr InterfaceHandle);
// Use this declaration to retrieve DEVICE_SPEED (the only currently defined InformationType).
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_QueryDeviceInformation(IntPtr InterfaceHandle, UInt32 InformationType, ref UInt32 BufferLength, ref Byte Buffer);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_QueryInterfaceSettings(IntPtr InterfaceHandle, Byte AlternateInterfaceNumber, ref USB_INTERFACE_DESCRIPTOR UsbAltInterfaceDescriptor);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_QueryPipe(IntPtr InterfaceHandle, Byte AlternateInterfaceNumber, Byte PipeIndex, ref WINUSB_PIPE_INFORMATION PipeInformation);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_ReadPipe(IntPtr InterfaceHandle, Byte PipeID, Byte[] Buffer, UInt32 BufferLength, ref UInt32 LengthTransferred, IntPtr Overlapped);
// Two declarations for WinUsb_SetPipePolicy.
// Use this one when the returned Value is a Byte (all except PIPE_TRANSFER_TIMEOUT):
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_SetPipePolicy(IntPtr InterfaceHandle, Byte PipeID, UInt32 PolicyType, UInt32 ValueLength, ref Byte Value);
// Use this alias when the returned Value is a UInt32 (PIPE_TRANSFER_TIMEOUT only):
[DllImport("winusb.dll", SetLastError = true, EntryPoint = "WinUsb_SetPipePolicy")]
internal static extern Boolean WinUsb_SetPipePolicyI(IntPtr InterfaceHandle, Byte PipeID, UInt32 PolicyType, UInt32 ValueLength, ref UInt32 Value);
[DllImport("winusb.dll", SetLastError = true)]
internal static extern Boolean WinUsb_WritePipe(IntPtr InterfaceHandle, Byte PipeID, Byte[] Buffer, UInt32 BufferLength, ref UInt32 LengthTransferred, IntPtr Overlapped);
}
public class DevMgmtAPI
{
// from dbt.h
internal const Int32 DBT_DEVICEARRIVAL = 0X8000;
internal const Int32 DBT_DEVICEREMOVECOMPLETE = 0X8004;
internal const Int32 DBT_DEVTYP_DEVICEINTERFACE = 5;
internal const Int32 DBT_DEVTYP_HANDLE = 6;
internal const Int32 DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 4;
internal const Int32 DEVICE_NOTIFY_SERVICE_HANDLE = 1;
internal const Int32 DEVICE_NOTIFY_WINDOW_HANDLE = 0;
internal const Int32 WM_DEVICECHANGE = 0X219;
// from setupapi.h
internal const Int32 DIGCF_PRESENT = 2;
internal const Int32 DIGCF_DEVICEINTERFACE = 0X10;
// Two declarations for the DEV_BROADCAST_DEVICEINTERFACE structure.
// Use this one in the call to RegisterDeviceNotification() and
// in checking dbch_devicetype in a DEV_BROADCAST_HDR structure:
[StructLayout(LayoutKind.Sequential)]
internal class DEV_BROADCAST_DEVICEINTERFACE
{
internal Int32 dbcc_size;
internal Int32 dbcc_devicetype;
internal Int32 dbcc_reserved;
internal Guid dbcc_classguid;
internal Int16 dbcc_name;
}
// Use this to read the dbcc_name String and classguid:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
internal class DEV_BROADCAST_DEVICEINTERFACE_1
{
internal Int32 dbcc_size;
internal Int32 dbcc_devicetype;
internal Int32 dbcc_reserved;
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.U1, SizeConst = 16)]
internal Byte[] dbcc_classguid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
internal Char[] dbcc_name;
}
[StructLayout(LayoutKind.Sequential)]
internal class DEV_BROADCAST_HDR
{
internal Int32 dbch_size;
internal Int32 dbch_devicetype;
internal Int32 dbch_reserved;
}
internal struct SP_DEVICE_INTERFACE_DATA
{
internal Int32 cbSize;
internal System.Guid InterfaceClassGuid;
internal Int32 Flags;
internal IntPtr Reserved;
}
internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
internal Int32 cbSize;
internal String DevicePath;
}
internal struct SP_DEVINFO_DATA
{
internal Int32 cbSize;
internal System.Guid ClassGuid;
internal Int32 DevInst;
internal Int32 Reserved;
}
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, Int32 Flags);
[DllImport("setupapi.dll", SetLastError = true)]
internal static extern Int32 SetupDiCreateDeviceInfoList(ref System.Guid ClassGuid, Int32 hwndParent);
[DllImport("setupapi.dll", SetLastError = true)]
internal static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi.dll", SetLastError = true)]
internal static extern Boolean SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref System.Guid InterfaceClassGuid, Int32 MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern IntPtr SetupDiGetClassDevs(ref System.Guid ClassGuid, IntPtr Enumerator, IntPtr hwndParent, Int32 Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern Boolean SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr DeviceInterfaceDetailData, Int32 DeviceInterfaceDetailDataSize, ref Int32 RequiredSize, IntPtr DeviceInfoData);
[DllImport("user32.dll", SetLastError = true)]
internal static extern Boolean UnregisterDeviceNotification(IntPtr Handle);
internal static Boolean FindDeviceByGuid(System.Guid myGuid, ref String[] devicePathNames)
{
Int32 bufferSize = 0;
IntPtr detailDataBuffer = IntPtr.Zero;
Boolean deviceFound;
IntPtr deviceInfoSet = new System.IntPtr();
Boolean lastDevice = false;
Int32 memberIndex = 0;
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
Boolean success;
ArrayList devicePathArray = new ArrayList();
String devicePathName = null;
devicePathNames = null;
try
{
deviceInfoSet = SetupDiGetClassDevs(ref myGuid, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
deviceFound = false;
memberIndex = 0;
MyDeviceInterfaceData.cbSize = Marshal.SizeOf(MyDeviceInterfaceData);
do
{
success = SetupDiEnumDeviceInterfaces(deviceInfoSet, IntPtr.Zero, ref myGuid, memberIndex, ref MyDeviceInterfaceData);
if (!success) lastDevice = true;
else
{
success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, ref bufferSize, IntPtr.Zero);
detailDataBuffer = Marshal.AllocHGlobal(bufferSize);
Marshal.WriteInt32(detailDataBuffer, (IntPtr.Size == 4) ? (4 + Marshal.SystemDefaultCharSize) : 8);
success = SetupDiGetDeviceInterfaceDetail(deviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, bufferSize, ref bufferSize, IntPtr.Zero);
IntPtr pDevicePathName = new IntPtr(detailDataBuffer.ToInt32() + 4);
devicePathName = Marshal.PtrToStringAuto(pDevicePathName);
deviceFound = true;
devicePathArray.Add(devicePathName);
}
memberIndex = memberIndex + 1;
}
while (!((lastDevice == true)));
devicePathNames = new string[devicePathArray.Count];
devicePathArray.CopyTo(devicePathNames);
return deviceFound;
}
catch
{
devicePathNames = null;
throw;
}
finally
{
if (detailDataBuffer != IntPtr.Zero) Marshal.FreeHGlobal(detailDataBuffer);
if (deviceInfoSet != IntPtr.Zero) SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
}
internal static string GetDevicePath(System.Guid guid)
{
String[] devicePathNames = null;
if (!FindDeviceByGuid(guid, ref devicePathNames)) return (null);
if (null == devicePathNames) return (null);
return (devicePathNames[0]);
}
}
internal class FileIO
{
internal const Int32 FILE_ATTRIBUTE_NORMAL = 0X80;
internal const Int32 FILE_FLAG_OVERLAPPED = 0X40000000;
internal const Int32 FILE_SHARE_READ = 1;
internal const Int32 FILE_SHARE_WRITE = 2;
internal const UInt32 GENERIC_READ = 0X80000000;
internal const UInt32 GENERIC_WRITE = 0X40000000;
internal const Int32 INVALID_HANDLE_VALUE = -1;
internal const Int32 OPEN_EXISTING = 3;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
internal static extern SafeFileHandle CreateFile(String lpFileName, UInt32 dwDesiredAccess, Int32 dwShareMode, IntPtr lpSecurityAttributes, Int32 dwCreationDisposition, Int32 dwFlagsAndAttributes, Int32 hTemplateFile);
}
}
|
|
|