Files
DP44/Common/DTS.Common.IConnection/.svn/pristine/62/6232704382de4ad16b303d7df1473a15ba337ea0.svn-base

423 lines
13 KiB
Plaintext
Raw Normal View History

2026-04-17 14:55:32 -04:00
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Threading;
using System.Threading.Tasks;
using DTS.Common.DASResource;
using DTS.Common.Interface.Connection;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.WINUSBConnection
{
public class UsbRecAsyncResult : 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 class CDCUSBConnection : IConnection
{
/// <summary>
/// returns true if the das has been soft disconnected or not
/// </summary>
public bool IsSoftDisconnected { get; private set; } = false;
/// <summary>
/// connect the das
/// :note does nothing for CDCUSB, we don't have a soft disconnect option
/// </summary>
public void SoftConnect()
{
}
/// <summary>
/// disconnect the das
/// :note does nothing for CDCUSB, we don't have a soft disconnect option
/// </summary>
public void SoftDisconnect()
{
}
void IConnection.KeepAliveErrorReceived()
{
}
public string GetConnectionData() { return ""; }
public const int DTS_VENDOR_ID = 0x1CB9;
public const string DTS_VENDOR_ID_STR = "VID_1CB9";
private const string DTS_TSR2_CDCUSB_PRODUCT_ID_STR = "PID_001A";
private static List<string> _regKeys;
private static readonly object KEY_LOCK = new object();
public static IList<string> RegKeys
{
get
{
lock (KEY_LOCK)
{
if (null != _regKeys) return _regKeys;
_regKeys = new List<string>();
ReadTSR2CDCUSBRegKeys();
}
return _regKeys;
}
}
/// <summary>
/// Searches the system registry for a key that corresponds to the Peak CAN USB
/// vendor and product ID.
/// </summary>
internal static void ReadTSR2CDCUSBRegKeys()
{
var ourKey = ReadOurNameRegistryKey();
if (null == ourKey) { return; }
foreach (var subKey in ourKey.GetSubKeyNames())
{
RegKeys.Add(subKey);
}
}
internal static Microsoft.Win32.RegistryKey ReadOurNameRegistryKey()
{
var key = Microsoft.Win32.Registry.LocalMachine;
const string ourName = @"SYSTEM\CurrentControlSet\Enum\USB\" + DTS_VENDOR_ID_STR + "&" + DTS_TSR2_CDCUSB_PRODUCT_ID_STR;
key = key.OpenSubKey(ourName);
return key;
}
/// <summary>
/// current upload rate in b/s
/// </summary>
/// <returns></returns>
public double GetCurrentUploadRate() { return 0D; }
/// <summary>
/// current download rate in b/s
/// </summary>
/// <returns></returns>
public double GetCurrentDownloadRate() { return 0D; }
public event EventHandler OnDisconnected;
private int _baudRate = 9600;
private Parity _parity = Parity.None;
private StopBits _stopBits = StopBits.One;
private const int DATA_BITS = 8;
public string PortName { get; set; }
private readonly SerialPort _comPort = new SerialPort();
private string _devicePathname;
protected bool _Connected;
protected volatile bool Disposed;
protected volatile bool Disposing;
public bool Connected => _Connected;
public string ConnectString => _devicePathname;
public System.Net.Sockets.SocketFlags Flags { get; set; }
private class AUSBRecFix
{
public readonly AsyncCallback Callback;
public readonly UsbRecAsyncResult USBResult;
public AUSBRecFix(AsyncCallback callback, UsbRecAsyncResult usbResult)
{
Callback = callback;
USBResult = usbResult;
}
}
public CDCUSBConnection()
{
Disposed = false;
Disposing = false;
_Connected = false;
}
~CDCUSBConnection()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
// Use SupressFinalize in case a subclass
// of this type implements a finalizer.
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
// make sure we're not already disposed
if (Disposed)
return;
if (disposing)
{
Disposing = true;
}
if (_comPort.IsOpen)
{
_comPort.Close();
_Connected = false;
}
Disposed = true;
Disposing = false;
}
public void Create(string connectString)
{
//Create(connectString); - this is recursive!
}
public void Create(string connectString, string hostIPAddress)
{
foreach (var regKey in RegKeys)
{
if (!connectString.Contains(regKey.ToLower())) continue;
var ourKey = ReadOurNameRegistryKey();
ourKey = ourKey.OpenSubKey(regKey);
ourKey = ourKey?.OpenSubKey("Device Parameters");
var value = (string)ourKey?.GetValue("PortName");
PortName = value;
break;
}
_devicePathname = connectString;
}
#region Disconnect
public IAsyncResult BeginDisconnect(bool reuseSocket,
AsyncCallback cb,
Object state)
{
var rar = new UsbRecAsyncResult
{
AsyncState = state,
AsyncWaitHandle = new ManualResetEvent(false),
CompletedSynchronously = false,
IsCompleted = false,
buffer = null,
Offset = 0,
Size = 0
};
if (!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
{
throw new Exception(DASResource.Strings.CDCUSBConnection_BeginDisconnect_Err1);
}
return rar;
}
public void EndDisconnect(IAsyncResult ar)
{
var rar = ar as UsbRecAsyncResult;
if (_comPort.IsOpen)
{
_comPort.Close();
_Connected = false;
_comPort.Dispose();
}
((ManualResetEvent)rar?.AsyncWaitHandle)?.Set();
}
#endregion
#region Accept
public IAsyncResult BeginAccept(AsyncCallback callback,
object state)
{
throw new NotSupportedException();
}
public IConnection EndAccept(IAsyncResult asyncResult)
{
throw new NotSupportedException();
}
#endregion
#region Listen
public void Listen(int backlog)
{
throw new NotSupportedException();
}
#endregion
#region Bind
public void Bind(int port)
{
throw new NotSupportedException();
}
#endregion
#region Connect
public IAsyncResult BeginConnect(AsyncCallback cb, object state)
{
var rar = new UsbRecAsyncResult
{
AsyncState = state,
AsyncWaitHandle = new ManualResetEvent(false),
CompletedSynchronously = false,
IsCompleted = false,
buffer = null,
Offset = 0,
Size = 0
};
if (!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
{
// "USBConnection.BeginConnect: Unable to enqueue function"
throw new Exception(DASResource.Strings.CDCUSBConnection_BeginConnect_Err1);
}
return rar;
}
private void NetCallbackFix(object obj)
{
try
{
if (Disposed) return;
var ausbrf = obj as AUSBRecFix;
ausbrf?.Callback(ausbrf.USBResult);
}
catch (Exception ex)
{
APILogger.Log(@"PcanUsbConnection.NetCallbackFix: Exception " + ex.Message + @" " + ex.StackTrace);
}
}
public void EndConnect(IAsyncResult ar)
{
var rar = ar as UsbRecAsyncResult;
if (_comPort.IsOpen)
{
_comPort.Close();
_Connected = false;
}
_comPort.BaudRate = _baudRate;
_comPort.DataBits = DATA_BITS;
_comPort.StopBits = _stopBits;
_comPort.Parity = _parity;
_comPort.PortName = PortName;
try
{
_comPort.Open();
}
catch (Exception)
{
_Connected = false;
}
_Connected = true;
((ManualResetEvent)rar?.AsyncWaitHandle)?.Set();
}
#endregion
#region Send
public IAsyncResult BeginSend(byte[] buffer, int offset, int size,
AsyncCallback cb, object state)
{
var rar = new UsbRecAsyncResult
{
AsyncState = state,
AsyncWaitHandle = new ManualResetEvent(false),
CompletedSynchronously = false,
IsCompleted = false,
buffer = buffer,
Offset = offset,
Size = size
};
if (!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
{
// "WINUSBConnection.BeginSend: Unable to enqueue function"
throw new Exception(DASResource.Strings.CDCUSBConnection_BeginSend_Err1);
}
return rar;
}
public int EndSend(IAsyncResult ar)
{
var rar = ar as UsbRecAsyncResult;
if (null == rar)
{
return 0;
}
_comPort.Write(rar.buffer, 0, rar.Size);
((ManualResetEvent)rar.AsyncWaitHandle).Set();
return rar.Size;
}
public Task<int> SendAsync(byte[] sendBuffer, int bufferStartOffset, int bufferSizeToSend)
{
return Task<int>.Factory.FromAsync(
(callback, state) => BeginSend(sendBuffer, bufferStartOffset, bufferSizeToSend, callback, state),
EndSend, state: null
);
}
#endregion
#region Receive
public IAsyncResult BeginReceive(byte[] buffer, int offset, int size,
AsyncCallback cb, object state)
{
var rar = new UsbRecAsyncResult
{
AsyncState = state,
AsyncWaitHandle = new ManualResetEvent(false),
CompletedSynchronously = false,
IsCompleted = false,
buffer = buffer,
Offset = offset,
Size = size
};
if (!ThreadPool.QueueUserWorkItem(NetCallbackFix, new AUSBRecFix(cb, rar)))
{
// "WINUSBConnection.BeginReceive: Unable to enqueue function"
throw new Exception(DASResource.Strings.CDCUSBConnection_BeginReceive_Err1);
}
return rar;
}
//private DateTime _lastHeartbeat;
public int EndReceive(IAsyncResult ar)
{
var rar = ar as UsbRecAsyncResult;
int bytesRead;
do
{
bytesRead = _comPort.Read(rar.buffer, 0, rar.Size);
if (0 == bytesRead)
{
Thread.Sleep(1);
}
} while (0 == bytesRead);
((ManualResetEvent)rar.AsyncWaitHandle).Set();
return bytesRead;
}
#endregion
}
}