pos/is4c-nf/scale-drivers/drivers/NewMagellan/USB-Win32.cs
using System;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
namespace USBLayer {
public class USBWrapper_Win32 : USBWrapper {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct Overlapped {
public uint Internal;
public uint InternalHigh;
public uint Offset;
public uint OffsetHigh;
public IntPtr Event;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct DeviceInterfaceData {
public int Size;
public Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
protected struct HidCaps {
public short Usage;
public short UsagePage;
public short InputReportByteLength;
public short OutputReportByteLength;
public short FeatureReportByteLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 17)]
public short[] Reserved;
public short NumberLinkCollectionNodes;
public short NumberInputButtonCaps;
public short NumberInputValueCaps;
public short NumberInputDataIndices;
public short NumberOutputButtonCaps;
public short NumberOutputValueCaps;
public short NumberOutputDataIndices;
public short NumberFeatureButtonCaps;
public short NumberFeatureValueCaps;
public short NumberFeatureDataIndices;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DeviceInterfaceDetailData {
public int Size;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
public class DeviceBroadcastInterface {
public int Size;
public int DeviceType;
public int Reserved;
public Guid ClassGuid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Name;
}
public const int WM_DEVICECHANGE = 0x0219;
public const int DEVICE_ARRIVAL = 0x8000;
public const int DEVICE_REMOVECOMPLETE = 0x8004;
protected const int DIGCF_PRESENT = 0x02;
protected const int DIGCF_DEVICEINTERFACE = 0x10;
protected const int DEVTYP_DEVICEINTERFACE = 0x05;
protected const int DEVICE_NOTIFY_WINDOW_HANDLE = 0;
protected const uint PURGE_TXABORT = 0x01;
protected const uint PURGE_RXABORT = 0x02;
protected const uint PURGE_TXCLEAR = 0x04;
protected const uint PURGE_RXCLEAR = 0x08;
protected const uint GENERIC_READ = 0x80000000;
protected const uint GENERIC_WRITE = 0x40000000;
protected const uint FILE_FLAG_OVERLAPPED = 0x40000000;
protected const uint OPEN_EXISTING = 3;
protected const uint ERROR_IO_PENDING = 997;
protected const uint INFINITE = 0xFFFFFFFF;
public static IntPtr NullHandle = IntPtr.Zero;
protected static IntPtr InvalidHandleValue = new IntPtr(-1);
private IntPtr native_handle;
private SafeFileHandle safe_handle;
[DllImport("hid.dll", SetLastError = true)] protected static extern void HidD_GetHidGuid(out Guid gHid);
[DllImport("setupapi.dll", SetLastError = true)] protected static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, [MarshalAs(UnmanagedType.LPStr)] string strEnumerator, IntPtr hParent, uint nFlags);
[DllImport("setupapi.dll", SetLastError = true)] protected static extern int SetupDiDestroyDeviceInfoList(IntPtr lpInfoSet);
[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiEnumDeviceInterfaces(IntPtr lpDeviceInfoSet, uint nDeviceInfoData, ref Guid gClass, uint nIndex, ref DeviceInterfaceData oInterfaceData);
[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr lpDeviceInfoSet, ref DeviceInterfaceData oInterfaceData, IntPtr lpDeviceInterfaceDetailData, uint nDeviceInterfaceDetailDataSize, ref uint nRequiredSize, IntPtr lpDeviceInfoData);
[DllImport("setupapi.dll", SetLastError = true)] protected static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr lpDeviceInfoSet, ref DeviceInterfaceData oInterfaceData, ref DeviceInterfaceDetailData oDetailData, uint nDeviceInterfaceDetailDataSize, ref uint nRequiredSize, IntPtr lpDeviceInfoData);
[DllImport("user32.dll", SetLastError = true)] protected static extern IntPtr RegisterDeviceNotification(IntPtr hwnd, DeviceBroadcastInterface oInterface, uint nFlags);
[DllImport("user32.dll", SetLastError = true)] protected static extern bool UnregisterDeviceNotification(IntPtr hHandle);
[DllImport("hid.dll", SetLastError = true)] protected static extern bool HidD_GetPreparsedData(IntPtr hFile, out IntPtr lpData);
[DllImport("hid.dll", SetLastError = true)] protected static extern bool HidD_FreePreparsedData(ref IntPtr pData);
[DllImport("hid.dll", SetLastError = true)] protected static extern int HidP_GetCaps(IntPtr lpData, out HidCaps oCaps);
[DllImport("kernel32.dll", SetLastError = true)] protected static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPStr)] string strName, uint nAccess, uint nShareMode, IntPtr lpSecurity, uint nCreationFlags, uint nAttributes, IntPtr lpTemplate);
[DllImport("kernel32.dll", SetLastError = true)] protected static extern int CloseHandle(IntPtr hFile);
/**
* Get a handle for USB device file
* @param filename the name of the file OR vendor and device ids formatted as "vid&pid"
* @param report_size [optional] report size in bytes
* @return open read/write Stream
*/
public override Stream GetUSBHandle(string filename, int report_size){
if (filename.IndexOf("&") > 0){
String[] parts = filename.Split(new Char[]{'&'});
if (parts.Length != 2){
System.Console.WriteLine(filename);
return null;
}
try {
filename = GetDeviceFilename(Convert.ToInt32(parts[0]),Convert.ToInt32(parts[1]));
}
catch(Exception ex){
System.Console.WriteLine(ex.ToString());
return null;
}
}
native_handle = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, IntPtr.Zero);
if (native_handle != InvalidHandleValue){
IntPtr lpData;
if (HidD_GetPreparsedData(native_handle, out lpData)){
HidCaps oCaps;
HidP_GetCaps(lpData, out oCaps); // extract the device capabilities from the internal buffer
int inp = oCaps.InputReportByteLength; // get the input...
int outp = oCaps.OutputReportByteLength; // ... and output report length
HidD_FreePreparsedData(ref lpData);
System.Console.WriteLine("Input: {0}, Output: {1}",inp, outp);
}
safe_handle = new SafeFileHandle(native_handle, true);
return new FileStream(safe_handle, FileAccess.Read | FileAccess.Write, report_size, true);
// old method that works but generates obsolete warnings
// return new FileStream(native_handle, FileAccess.Read | FileAccess.Write, true, report_size, true);
}
return null;
}
public override void CloseUSBHandle(){
try {
safe_handle.Close();
CloseHandle(native_handle);
}
catch(Exception){}
}
private String GetDeviceFilename(int vid, int pid){
string devname = string.Format("vid_{0:x4}&pid_{1:x4}", vid, pid);
string filename = null;
Guid gHid;
HidD_GetHidGuid(out gHid);
IntPtr hInfoSet = SetupDiGetClassDevs(ref gHid, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
DeviceInterfaceData oInterface = new DeviceInterfaceData();
oInterface.Size = Marshal.SizeOf(oInterface);
int nIndex = 0;
while (SetupDiEnumDeviceInterfaces(hInfoSet, 0, ref gHid, (uint)nIndex, ref oInterface)) {
string strDevicePath = GetDevicePath(hInfoSet, ref oInterface);
System.Console.WriteLine(strDevicePath);
if (strDevicePath.IndexOf(devname) >= 0){
filename = strDevicePath;
break;
}
nIndex++;
}
SetupDiDestroyDeviceInfoList(hInfoSet);
return filename;
}
private static string GetDevicePath(IntPtr hInfoSet, ref DeviceInterfaceData oInterface){
uint nRequiredSize = 0;
if (!SetupDiGetDeviceInterfaceDetail(hInfoSet, ref oInterface, IntPtr.Zero, 0, ref nRequiredSize, IntPtr.Zero)) {
DeviceInterfaceDetailData oDetail = new DeviceInterfaceDetailData();
oDetail.Size = (IntPtr.Size==8) ? 8 : 5;
if (SetupDiGetDeviceInterfaceDetail(hInfoSet, ref oInterface, ref oDetail, nRequiredSize, ref nRequiredSize, IntPtr.Zero)){
return oDetail.DevicePath;
}
}
return null;
}
} // end class
} // end namespace