You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
11 KiB
315 lines
11 KiB
using System;
|
|
using System.Threading;
|
|
using System.Diagnostics;
|
|
using LibUsbDotNet;
|
|
using LibUsbDotNet.Main;
|
|
|
|
namespace SSComm
|
|
{
|
|
|
|
public class USBGen_LibUSB : IUniComm
|
|
{
|
|
public bool Connected { get; private set; } = false;
|
|
|
|
public Int32 lBytesSent;
|
|
public Int32 lBytesReceived;
|
|
|
|
public const Int32 RXFIFOSIZE = 32768;
|
|
public const Int32 TXFIFOSIZE = 16384;
|
|
|
|
public Int32 DevVID = Int32.MaxValue;
|
|
public Int32 DevPID = Int32.MaxValue;
|
|
public Int32 DevRevision = Int32.MaxValue;
|
|
public string DevSerialNumber = string.Empty;
|
|
|
|
public Guid DevGUID = Guid.Empty;
|
|
|
|
public event EventHandler DataReceived;
|
|
|
|
private UsbDevice MyUSBDevice;
|
|
private UsbDeviceFinder MyUSBDeviceFinder;
|
|
private IUsbDevice WholeUSBDevice;
|
|
private UsbEndpointWriter MyUSBWriter;
|
|
private UsbEndpointReader MyUSBReader;
|
|
private UsbSetupPacket MyUSBSetupPacket;
|
|
|
|
private byte[] RXFIFO = new byte[RXFIFOSIZE];
|
|
private Int32 RXReadPos;
|
|
private Int32 RXWritePos;
|
|
|
|
private byte[] TXFIFO = new byte[TXFIFOSIZE];
|
|
private Int32 TXReadPos;
|
|
private Int32 TXWritePos;
|
|
|
|
private System.Threading.Thread bkThread;
|
|
private bool bkThExit;
|
|
private ManualResetEvent bkThInterrupt = new ManualResetEvent(false);
|
|
|
|
public bool Connect()
|
|
{
|
|
bool rv = false;
|
|
rv = false;
|
|
Disconnect();
|
|
MyUSBDeviceFinder = new UsbDeviceFinder(DevVID, DevPID, DevRevision, DevSerialNumber, DevGUID);
|
|
MyUSBDevice = UsbDevice.OpenUsbDevice(MyUSBDeviceFinder);
|
|
if (MyUSBDevice != null)
|
|
{
|
|
WholeUSBDevice = MyUSBDevice as IUsbDevice;
|
|
if (!ReferenceEquals(WholeUSBDevice, null))
|
|
{
|
|
WholeUSBDevice.SetConfiguration(1);
|
|
WholeUSBDevice.ClaimInterface(0);
|
|
}
|
|
MyUSBWriter = MyUSBDevice.OpenEndpointWriter(WriteEndpointID.Ep01);
|
|
MyUSBReader = MyUSBDevice.OpenEndpointReader(ReadEndpointID.Ep01, 4096);
|
|
MyUSBReader.DataReceived += MyUSBReader_DataReceived;
|
|
MyUSBReader.DataReceivedEnabled = true;
|
|
|
|
MyUSBSetupPacket.RequestType = (byte)(UsbCtrlFlags.RequestType_Vendor | UsbCtrlFlags.Recipient_Interface | UsbCtrlFlags.Direction_In);
|
|
MyUSBSetupPacket.Request = 1;
|
|
MyUSBSetupPacket.Value = 0;
|
|
MyUSBSetupPacket.Length = 4;
|
|
|
|
bkThread = new System.Threading.Thread(this.Th_DoWork);
|
|
bkThExit = false;
|
|
bkThread.Start();
|
|
rv = true;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
public void Disconnect()
|
|
{
|
|
if (bkThread != null)
|
|
{
|
|
bkThExit = true;
|
|
bkThInterrupt.Set();
|
|
if (bkThread.ThreadState == System.Threading.ThreadState.Running) bkThread.Join();
|
|
}
|
|
bkThread = null;
|
|
if (MyUSBDevice != null)
|
|
{
|
|
if (MyUSBDevice.IsOpen)
|
|
{
|
|
WholeUSBDevice = MyUSBDevice as IUsbDevice;
|
|
if (!ReferenceEquals(WholeUSBDevice, null))
|
|
{
|
|
WholeUSBDevice.ReleaseInterface(0);
|
|
}
|
|
MyUSBReader.DataReceivedEnabled = false;
|
|
MyUSBReader.DataReceived -= MyUSBReader_DataReceived;
|
|
MyUSBDevice.Close();
|
|
}
|
|
MyUSBDevice = null;
|
|
WholeUSBDevice = null;
|
|
MyUSBDeviceFinder = null;
|
|
MyUSBReader = null;
|
|
MyUSBWriter = null;
|
|
}
|
|
}
|
|
|
|
public void Init()
|
|
{
|
|
Disconnect();
|
|
lBytesSent = 0;
|
|
lBytesReceived = 0;
|
|
RXReadPos = 0;
|
|
RXWritePos = 0;
|
|
DevVID = Int32.MaxValue;
|
|
DevPID = Int32.MaxValue;
|
|
DevRevision = Int32.MaxValue;
|
|
DevGUID = Guid.Empty;
|
|
}
|
|
|
|
public Int32 BytesSent()
|
|
{
|
|
return lBytesSent;
|
|
}
|
|
|
|
public Int32 BytesReceived()
|
|
{
|
|
return lBytesReceived;
|
|
}
|
|
|
|
public Int32 RXDataCount
|
|
{
|
|
get
|
|
{
|
|
Int32 i;
|
|
i = RXWritePos - RXReadPos;
|
|
if (i < 0) i += RXFIFOSIZE;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
public byte ReadByte()
|
|
{
|
|
byte rv;
|
|
if (RXWritePos != RXReadPos)
|
|
{
|
|
rv = RXFIFO[RXReadPos];
|
|
RXReadPos = (RXReadPos + 1) % RXFIFOSIZE;
|
|
return rv;
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("SSComm(USBGen_LibUSB).ReadByte: RX FIFO empty!");
|
|
}
|
|
}
|
|
|
|
public Int32 Read(ref byte[] DBuffer, Int32 DOffset, Int32 MaxBytes)
|
|
{
|
|
Int32 i;
|
|
if (MaxBytes < 0) MaxBytes = 0;
|
|
if (MaxBytes > 0)
|
|
{
|
|
i = RXDataCount;
|
|
if (MaxBytes > i) MaxBytes = i;
|
|
if (MaxBytes < i) i = MaxBytes;
|
|
while (i > 0)
|
|
{
|
|
DBuffer[DOffset] = RXFIFO[RXReadPos];
|
|
DOffset += 1;
|
|
RXReadPos = (RXReadPos + 1) % RXFIFOSIZE;
|
|
i -= 1;
|
|
}
|
|
}
|
|
return MaxBytes;
|
|
}
|
|
|
|
public Int32 TXFreeSpace
|
|
{
|
|
get
|
|
{
|
|
Int32 i;
|
|
i = TXWritePos - TXReadPos;
|
|
if (i < 0) i += TXFIFOSIZE;
|
|
i = TXFIFOSIZE - i;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
public void WriteByte(ref byte wb, bool dow = true)
|
|
{
|
|
if (TXFreeSpace > 0)
|
|
{
|
|
TXFIFO[TXWritePos] = wb;
|
|
TXWritePos = (TXWritePos + 1) % TXFIFOSIZE;
|
|
if (dow && (bkThread != null)) bkThInterrupt.Set();
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("SSComm(USBGen_LibUSB).WriteByte: TX FIFO Full!");
|
|
}
|
|
}
|
|
|
|
public bool Write(ref byte[] DBuffer, int DOffset, int NumBytes)
|
|
{
|
|
Int32 i;
|
|
if (NumBytes > TXFreeSpace) throw new Exception("Not enough space in TX buffer.");
|
|
for (i = 0; i < NumBytes; i++)
|
|
{
|
|
TXFIFO[TXWritePos] = DBuffer[DOffset + i];
|
|
TXWritePos = (TXWritePos + 1) % TXFIFOSIZE;
|
|
}
|
|
if (bkThread != null)bkThInterrupt.Set();
|
|
return true;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
Disconnect();
|
|
}
|
|
|
|
private void MyUSBReader_DataReceived(object sender, LibUsbDotNet.Main.EndpointDataEventArgs e)
|
|
{
|
|
Int32 i;
|
|
if (e.Count > 0)
|
|
{
|
|
lBytesReceived += e.Count;
|
|
if (RXDataCount + e.Count < RXFIFOSIZE)
|
|
{
|
|
for (i = 0; i < e.Count; i++)
|
|
{
|
|
RXFIFO[RXWritePos] = e.Buffer[i];
|
|
RXWritePos = (RXWritePos + 1) % RXFIFOSIZE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("RX FIFO overflow");
|
|
}
|
|
if (DataReceived != null)
|
|
{
|
|
DataReceived(this, new EventArgs());
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Th_DoWork()
|
|
{
|
|
Int32 lDevMaxDataSize;
|
|
Int32 lDevWait;
|
|
Int32 lTXSize;
|
|
Int32[] i = new Int32[1];
|
|
bool TXSuccess;
|
|
lDevWait = 0;
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
if (TXReadPos != TXWritePos)
|
|
{
|
|
lDevWait += 1;
|
|
if (lDevWait > 1000) lDevWait = 1000;
|
|
if (MyUSBDevice != null)
|
|
{
|
|
if (MyUSBDevice.IsOpen)
|
|
{
|
|
if (MyUSBWriter != null)
|
|
{
|
|
//query how much data device can accept
|
|
if (MyUSBDevice.ControlTransfer(ref MyUSBSetupPacket, i, 4, out lTXSize))
|
|
{
|
|
if (lTXSize == 4)
|
|
{
|
|
lDevMaxDataSize = i[0];
|
|
//Debug.Print("Device can accept maximum " & lDevMaxDataSize & " byte(s)")
|
|
if (lDevMaxDataSize > 0)
|
|
{
|
|
lDevWait = 0;
|
|
lTXSize = TXWritePos - TXReadPos;
|
|
if (lTXSize < 0)
|
|
lTXSize += TXFIFOSIZE;
|
|
if (lTXSize > 0)
|
|
{
|
|
if (lTXSize > lDevMaxDataSize) lTXSize = lDevMaxDataSize;
|
|
if ((TXReadPos + lTXSize) >= TXFIFOSIZE) lTXSize = TXFIFOSIZE - TXReadPos;
|
|
TXSuccess = (MyUSBWriter.Write(TXFIFO, TXReadPos, lTXSize, 2000, out lTXSize) == ErrorCode.Success);
|
|
if (TXSuccess)
|
|
{
|
|
TXReadPos = (TXReadPos + lTXSize) % TXFIFOSIZE;
|
|
lBytesSent += lTXSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
bkThInterrupt.WaitOne(lDevWait);
|
|
bkThInterrupt.Reset();
|
|
}
|
|
else
|
|
{
|
|
bkThInterrupt.WaitOne(Timeout.Infinite);
|
|
bkThInterrupt.Reset();
|
|
}
|
|
if (bkThExit) break;
|
|
}
|
|
}
|
|
catch (ThreadAbortException) { }
|
|
}
|
|
}
|
|
}
|