486 lines
20 KiB
Plaintext
486 lines
20 KiB
Plaintext
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Runtime.InteropServices;
|
|
using DTS.DASLib.Connection.USBFramework;
|
|
using DTS.DASLib.DASResource;
|
|
|
|
namespace DTS.DASLib.Connection
|
|
{
|
|
public class HIDUSBConnection: IConnection
|
|
{
|
|
public double GetCurrentDownloadRate() { return 0D; }
|
|
public double GetCurrentUploadRate() { return 0D; }
|
|
|
|
public const int HIDSLICE_PID = 0x0003;
|
|
public const int DTS_VID = 0x1CB9;
|
|
protected bool _Connected;
|
|
|
|
protected int NumberOfInputBuffers = 0;
|
|
protected int _HIDHandle;
|
|
protected bool _MyDeviceDetected;
|
|
protected HIDevice _MyHID = new HIDevice();
|
|
protected int _ReadHandle;
|
|
protected int _WriteHandle;
|
|
protected byte[] InputReportBuffer;
|
|
protected FileIODeclarations.SECURITY_ATTRIBUTES Security;
|
|
protected string Device_Name;
|
|
private bool disposed;
|
|
|
|
public event EventHandler OnDisconnected;
|
|
|
|
public bool Connected { get { return _Connected; } }
|
|
|
|
public string ConnectString { get { return Device_Name; } }
|
|
|
|
public System.Net.Sockets.SocketFlags Flags { get; set; }
|
|
|
|
public string GetConnectionData() { return ""; }
|
|
|
|
public void Create(string ConnectString)
|
|
{
|
|
Device_Name = ConnectString;
|
|
}
|
|
|
|
~HIDUSBConnection()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
protected virtual void Dispose(bool disposing)
|
|
{
|
|
if(disposed)
|
|
return;
|
|
|
|
if(disposing)
|
|
{
|
|
try
|
|
{
|
|
FileIODeclarations.CloseHandle(_HIDHandle);
|
|
}
|
|
catch { }
|
|
try
|
|
{
|
|
FileIODeclarations.CloseHandle(_ReadHandle);
|
|
}
|
|
catch { }
|
|
try
|
|
{
|
|
FileIODeclarations.CloseHandle(_WriteHandle);
|
|
}
|
|
catch { }
|
|
_MyHID.Dispose();
|
|
_Connected = false;
|
|
}
|
|
disposed = true;
|
|
}
|
|
|
|
public IAsyncResult BeginDisconnect(bool reuseSocket,
|
|
AsyncCallback cb,
|
|
Object state)
|
|
{
|
|
HIDUSBRecAsyncResult rar = new HIDUSBRecAsyncResult();
|
|
rar.AsyncState = state;
|
|
rar.AsyncWaitHandle = new ManualResetEvent(false);
|
|
rar.CompletedSynchronously = false;
|
|
rar.IsCompleted = false;
|
|
rar.buffer = null;
|
|
rar.offset = 0;
|
|
rar.size = 0;
|
|
if(!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
|
|
{
|
|
// "HIDUSBConnection.BeginDisconnect: Unable to enqueue function"
|
|
throw new System.Exception(Strings.HIDUSBConnection_BeginDisconnect_Err1);
|
|
}
|
|
return rar;
|
|
}
|
|
|
|
public void EndDisconnect(IAsyncResult asyncResult)
|
|
{
|
|
int Result;
|
|
|
|
Result = FileIODeclarations.CloseHandle(_HIDHandle);
|
|
Result = FileIODeclarations.CloseHandle(_ReadHandle);
|
|
Result = FileIODeclarations.CloseHandle(_WriteHandle);
|
|
_Connected = false;
|
|
}
|
|
|
|
public IAsyncResult BeginAccept(AsyncCallback callback,
|
|
Object state)
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
public IConnection EndAccept(IAsyncResult asyncResult)
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
public void Bind(int port)
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
public void Listen(int backlog)
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
// Define a class of delegates that point to the Hid.DeviceReport.Read function.
|
|
// The delegate has the same parameters as Hid.DeviceReport.Read.
|
|
// Used for asynchronous reads from the device.
|
|
protected delegate void ReadInputReportDelegate(int readHandle,
|
|
int hidHandle,
|
|
int writeHandle,
|
|
ref bool myDeviceDetected,
|
|
ref byte[] readBuffer,
|
|
ref bool success);
|
|
|
|
private class AUSBRecFix
|
|
{
|
|
public AsyncCallback cb;
|
|
public HIDUSBRecAsyncResult res;
|
|
|
|
public AUSBRecFix(AsyncCallback _cb, HIDUSBRecAsyncResult _res)
|
|
{
|
|
cb = _cb;
|
|
res = _res;
|
|
}
|
|
}
|
|
|
|
public HIDUSBConnection()
|
|
{
|
|
disposed = false;
|
|
Security = new FileIODeclarations.SECURITY_ATTRIBUTES();
|
|
Security.lpSecurityDescriptor = 0;
|
|
Security.bInheritHandle = System.Convert.ToInt32(true);
|
|
Security.nLength = Marshal.SizeOf(Security);
|
|
_Connected = false;
|
|
}
|
|
|
|
public IAsyncResult BeginConnect(AsyncCallback cb, object state)
|
|
{
|
|
HIDUSBRecAsyncResult rar = new HIDUSBRecAsyncResult();
|
|
rar.AsyncState = state;
|
|
rar.AsyncWaitHandle = new ManualResetEvent(false);
|
|
rar.CompletedSynchronously = false;
|
|
rar.IsCompleted = false;
|
|
rar.buffer = null;
|
|
rar.offset = 0;
|
|
rar.size = 0;
|
|
if(!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
|
|
{
|
|
// "USBConnection.BeginConnect: Unable to enqueue function"
|
|
throw new System.Exception(Strings.USBConnection_BeginConnect_Err1);
|
|
}
|
|
return rar;
|
|
}
|
|
|
|
private void NetCallbackFix(object obj)
|
|
{
|
|
try
|
|
{
|
|
AUSBRecFix ausbrf = obj as AUSBRecFix;
|
|
ausbrf.cb(ausbrf.res);
|
|
}
|
|
catch(System.Exception ex)
|
|
{
|
|
System.Windows.Forms.MessageBox.Show("HIDUSBConnection.NetCallbackFix: Exception " + ex.Message + " " + ex.StackTrace);
|
|
}
|
|
}
|
|
|
|
public static string GetFirstConnectString()
|
|
{
|
|
#region Hack to connect just one recorder by manually finding the first one ...
|
|
int Result;
|
|
int _HIDHandle;
|
|
HIDevice _MyHID = new HIDevice();
|
|
FileIODeclarations.SECURITY_ATTRIBUTES Security;
|
|
|
|
Security = new FileIODeclarations.SECURITY_ATTRIBUTES();
|
|
Security.lpSecurityDescriptor = 0;
|
|
Security.bInheritHandle = System.Convert.ToInt32(true);
|
|
Security.nLength = Marshal.SizeOf(Security);
|
|
|
|
System.Guid HIDGuid = new Guid();
|
|
string GuidString;
|
|
string[] DevicePathName = new string[128];
|
|
|
|
HIDDeclarations.HidD_GetHidGuid(ref HIDGuid);
|
|
GuidString = HIDGuid.ToString();
|
|
DeviceManagement _MyDeviceManagement = new DeviceManagement();
|
|
bool DeviceFound = _MyDeviceManagement.FindDeviceFromGuid(HIDGuid, ref DevicePathName);
|
|
|
|
if (true == DeviceFound)
|
|
{
|
|
int MemberIndex = 0;
|
|
DeviceFound = false;
|
|
|
|
do
|
|
{
|
|
//GRV - this works and is a true copy of Axelson
|
|
_HIDHandle = FileIODeclarations.CreateFile(DevicePathName[MemberIndex],
|
|
0,
|
|
FileIODeclarations.FILE_SHARE_READ | FileIODeclarations.FILE_SHARE_WRITE,
|
|
ref Security, FileIODeclarations.OPEN_EXISTING, 0, 0);
|
|
|
|
if (_HIDHandle != FileIODeclarations.INVALID_HANDLE_VALUE)
|
|
{
|
|
// The returned handle is valid,
|
|
// so find out if this is the device we're looking for.
|
|
|
|
// Set the Size property of DeviceAttributes to the number of bytes in the structure.
|
|
//_MyHID.DeviceAttributes.Size = _MyHID.DeviceAttributes.ToString().Length;
|
|
_MyHID.DeviceAttributes.Size = Marshal.SizeOf(_MyHID.DeviceAttributes);
|
|
|
|
// ***
|
|
// API function:
|
|
// HidD_GetAttributes
|
|
// Purpose:
|
|
// Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID,
|
|
// Product ID, and Product Version Number for a device.
|
|
// Accepts:
|
|
// A handle returned by CreateFile.
|
|
// A pointer to receive a HIDD_ATTRIBUTES structure.
|
|
// Returns:
|
|
// True on success, False on failure.
|
|
// ***
|
|
Result = HIDDeclarations.HidD_GetAttributes(_HIDHandle, ref _MyHID.DeviceAttributes);
|
|
|
|
if (Result != 0)
|
|
{
|
|
// Find out if the device matches the one we're looking for.
|
|
if (_MyHID.DeviceAttributes.VendorID == DTS_VID &&
|
|
_MyHID.DeviceAttributes.ProductID == HIDSLICE_PID)
|
|
{
|
|
|
|
// It's the desired device.
|
|
DeviceFound = true;
|
|
|
|
// Close the device so it can be opened for real later
|
|
Result = FileIODeclarations.CloseHandle(_HIDHandle);
|
|
|
|
// return the device's name
|
|
return DevicePathName[MemberIndex];
|
|
}
|
|
else
|
|
{
|
|
|
|
// It's not a match, so close the handle.
|
|
DeviceFound = false;
|
|
Result = FileIODeclarations.CloseHandle(_HIDHandle);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// There was a problem in retrieving the information.
|
|
DeviceFound = false;
|
|
Result = FileIODeclarations.CloseHandle(_HIDHandle);
|
|
}
|
|
}
|
|
|
|
// Keep looking until we find the device or there are no more left to examine.
|
|
MemberIndex = MemberIndex + 1;
|
|
} while (!((DeviceFound == true) || (MemberIndex == DevicePathName.Length)));
|
|
}
|
|
|
|
return string.Empty;
|
|
|
|
#endregion // Hack to connect just one recorder by manually finding the first one ...
|
|
}
|
|
|
|
public void EndConnect(IAsyncResult ar)
|
|
{
|
|
int Result;
|
|
|
|
_HIDHandle = FileIODeclarations.CreateFile(ConnectString,
|
|
0,
|
|
FileIODeclarations.FILE_SHARE_READ | FileIODeclarations.FILE_SHARE_WRITE,
|
|
ref Security,
|
|
FileIODeclarations.OPEN_EXISTING,
|
|
0,
|
|
0);
|
|
if(_HIDHandle == FileIODeclarations.INVALID_HANDLE_VALUE)
|
|
{
|
|
// "HIDUSBConnection.EndConnect: Can't open {0} in Connect"
|
|
throw new System.Exception(string.Format(Strings.HIDUSBConnection_EndConnect_Err1, ConnectString));
|
|
}
|
|
|
|
// Set the Size property of DeviceAttributes to the number of bytes in the structure.
|
|
_MyHID.DeviceAttributes.Size = Marshal.SizeOf(_MyHID.DeviceAttributes);
|
|
|
|
// HidD_GetAttributes
|
|
// Purpose: Retrieves a HIDD_ATTRIBUTES structure containing the Vendor ID,
|
|
// Product ID, and Product Version Number for a device.
|
|
// Accepts: A handle returned by CreateFile.
|
|
// A pointer to receive a HIDD_ATTRIBUTES structure.
|
|
// Returns: True on success, False on failure.
|
|
Result = HIDDeclarations.HidD_GetAttributes(_HIDHandle, ref _MyHID.DeviceAttributes);
|
|
|
|
// Learn the capabilities of the device.
|
|
_MyHID.Capabilities = _MyHID.GetDeviceCapabilities(_HIDHandle);
|
|
|
|
//Find out if device is system mouse or keyboard //GRV
|
|
string HIDUsage = _MyHID.GetHIDUsage(_MyHID.Capabilities);
|
|
|
|
// Get and display the Input report buffer size.
|
|
GetInputReportBufferSize();
|
|
|
|
// Get another handle to use in overlapped ReadFiles (for requesting Input reports).
|
|
_ReadHandle = FileIODeclarations.CreateFile(ConnectString,
|
|
FileIODeclarations.GENERIC_READ,
|
|
FileIODeclarations.FILE_SHARE_READ | FileIODeclarations.FILE_SHARE_WRITE,
|
|
ref Security,
|
|
FileIODeclarations.OPEN_EXISTING,
|
|
0,
|
|
0);
|
|
|
|
_WriteHandle = FileIODeclarations.CreateFile(ConnectString,
|
|
FileIODeclarations.GENERIC_WRITE,
|
|
FileIODeclarations.FILE_SHARE_READ | FileIODeclarations.FILE_SHARE_WRITE,
|
|
ref Security,
|
|
FileIODeclarations.OPEN_EXISTING,
|
|
0,
|
|
0);
|
|
|
|
// (optional)
|
|
// Flush any waiting reports in the input buffer.
|
|
_MyHID.FlushQueue(_ReadHandle);
|
|
|
|
HIDevice.InputReport myInputReport = new HIDevice.InputReport();
|
|
|
|
// Define a delegate for the Read method of myInputReport.
|
|
ReadInputReportDelegate MyReadInputReportDelegate = new ReadInputReportDelegate(myInputReport.Read);
|
|
|
|
// Set the size of the Input report buffer.
|
|
InputReportBuffer = new byte[_MyHID.Capabilities.InputReportByteLength];
|
|
|
|
_Connected = true;
|
|
}
|
|
|
|
protected void GetInputReportBufferSize()
|
|
{
|
|
try
|
|
{
|
|
// Get the number of input buffers.
|
|
_MyHID.GetNumberOfInputBuffers(_HIDHandle, ref NumberOfInputBuffers);
|
|
|
|
}
|
|
catch(System.Exception ex)
|
|
{
|
|
// "HIDUSBConnection.GetInputReportBufferSize: Error during {0}"
|
|
throw new ApplicationException(string.Format(Strings.HIDUSBConnection_GetInputReportBufferSize_Err1, ex.Message));
|
|
}
|
|
|
|
}
|
|
|
|
public class HIDUSBRecAsyncResult: IAsyncResult
|
|
{
|
|
public object AsyncState { get; set; }
|
|
public WaitHandle AsyncWaitHandle { get; set; }
|
|
public bool CompletedSynchronously { get; set; }
|
|
public bool IsCompleted { get; set; }
|
|
public byte[] buffer { get; set; }
|
|
public int offset { get; set; }
|
|
public int size { get; set; }
|
|
}
|
|
|
|
public IAsyncResult BeginSend(byte[] buffer, int offset, int size,
|
|
AsyncCallback cb, object state)
|
|
{
|
|
if(_ReadHandle == FileIODeclarations.INVALID_HANDLE_VALUE || _WriteHandle == FileIODeclarations.INVALID_HANDLE_VALUE)
|
|
{
|
|
// "HIDUSBConnection.BeginSend: Invalid read or write handle"
|
|
throw new System.Exception(Strings.HIDUSBConnection_BeginSend_Err1);
|
|
}
|
|
HIDUSBRecAsyncResult rar = new HIDUSBRecAsyncResult();
|
|
rar.AsyncState = state;
|
|
rar.AsyncWaitHandle = new ManualResetEvent(false);
|
|
rar.CompletedSynchronously = false;
|
|
rar.IsCompleted = false;
|
|
rar.buffer = buffer;
|
|
rar.offset = offset;
|
|
rar.size = size;
|
|
if(!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
|
|
{
|
|
// "HIDUSBConnection.BeginSend: Unable to enqueue function"
|
|
throw new System.Exception(Strings.HIDUSBConnection_BeginSend_Err2);
|
|
}
|
|
return rar;
|
|
}
|
|
|
|
public int EndSend(IAsyncResult ar)
|
|
{
|
|
HIDUSBRecAsyncResult rar = ar as HIDUSBRecAsyncResult;
|
|
int bytesLeft = rar.size;
|
|
int maxOutputReportLength = _MyHID.Capabilities.OutputReportByteLength;
|
|
byte[] OutputReportBuffer = new byte[maxOutputReportLength];
|
|
OutputReportBuffer[0] = 0;
|
|
|
|
for(int i = 0; i < rar.size; i += (maxOutputReportLength - 1))
|
|
{
|
|
bytesLeft = rar.size - i;
|
|
int bytesToCopy = ((bytesLeft < OutputReportBuffer.Length - 1) ? bytesLeft : OutputReportBuffer.Length - 1);
|
|
Buffer.BlockCopy(rar.buffer, rar.offset + i, OutputReportBuffer, 1, bytesToCopy);
|
|
HIDevice.OutputReport myOutputReport = new HIDevice.OutputReport();
|
|
if(!myOutputReport.Write(OutputReportBuffer, _WriteHandle))
|
|
{
|
|
// "HIDUSBConnection.EndSend: Error writing report"
|
|
throw new System.Exception(Strings.HIDUSBConnection_EndSend_Err1);
|
|
}
|
|
}
|
|
return rar.size;
|
|
}
|
|
|
|
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size,
|
|
AsyncCallback cb, object state)
|
|
{
|
|
if(_ReadHandle == FileIODeclarations.INVALID_HANDLE_VALUE || _WriteHandle == FileIODeclarations.INVALID_HANDLE_VALUE)
|
|
{
|
|
// "HIDUSBConnection.BeginReceive: Invalid read or write handle"
|
|
throw new System.Exception(Strings.HIDUSBConnection_BeginReceive_Err1);
|
|
}
|
|
HIDUSBRecAsyncResult rar = new HIDUSBRecAsyncResult();
|
|
rar.AsyncState = state;
|
|
rar.AsyncWaitHandle = new ManualResetEvent(false);
|
|
rar.CompletedSynchronously = false;
|
|
rar.IsCompleted = false;
|
|
rar.buffer = buffer;
|
|
rar.offset = offset;
|
|
rar.size = size;
|
|
if(!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
|
|
{
|
|
// "HIDUSBConnection.BeginReceive: Unable to enqueue function"
|
|
throw new System.Exception(Strings.HIDUSBConnection_BeginReceive_Err2);
|
|
}
|
|
return rar;
|
|
}
|
|
|
|
public int EndReceive(IAsyncResult ar)
|
|
{
|
|
HIDUSBRecAsyncResult rar = ar as HIDUSBRecAsyncResult;
|
|
bool Success = false;
|
|
HIDevice.InputReport myInputReport = new HIDevice.InputReport();
|
|
//byte[] InputBuffer = new byte[rar.size+1];
|
|
myInputReport.Read(_ReadHandle, _HIDHandle, _WriteHandle, ref _MyDeviceDetected, ref InputReportBuffer, ref Success);
|
|
if(Success)
|
|
{
|
|
Buffer.BlockCopy(InputReportBuffer, 1, rar.buffer, rar.offset, InputReportBuffer.Length - 1);
|
|
rar.IsCompleted = true;
|
|
((ManualResetEvent)rar.AsyncWaitHandle).Set();
|
|
return rar.size;
|
|
}
|
|
((ManualResetEvent)rar.AsyncWaitHandle).Set();
|
|
return 0;
|
|
}
|
|
}
|
|
}
|