|
@@ -6,7 +6,7 @@ unit USBasp;
|
|
|
|
|
|
|
|
USBasp Class.
|
|
USBasp Class.
|
|
|
|
|
|
|
|
- Copyright (C) 2022 - 2025 Dimitrios Chr. Ioannidis.
|
|
|
|
|
|
|
+ Copyright (C) 2025 Dimitrios Chr. Ioannidis.
|
|
|
Nephelae - https://www.nephelae.eu
|
|
Nephelae - https://www.nephelae.eu
|
|
|
|
|
|
|
|
https://www.nephelae.eu/
|
|
https://www.nephelae.eu/
|
|
@@ -32,38 +32,9 @@ interface
|
|
|
|
|
|
|
|
uses
|
|
uses
|
|
|
Classes, SysUtils, syncobjs, hidapi,
|
|
Classes, SysUtils, syncobjs, hidapi,
|
|
|
- SPSCRingBuffer, USBasp_Threads;
|
|
|
|
|
|
|
+ SPSCRingBuffer;
|
|
|
|
|
|
|
|
const
|
|
const
|
|
|
- USBASP_SHARED_VID = $16C0;
|
|
|
|
|
- USBASP_SHARED_PID = $05DC;
|
|
|
|
|
-
|
|
|
|
|
- USBASP_FUNC_GETCAPABILITIES = 127;
|
|
|
|
|
-
|
|
|
|
|
- USBASP_CAP_0_TPI = 1;
|
|
|
|
|
- USBASP_CAP_PDI = 16;
|
|
|
|
|
- USBASP_CAP_2_SNHIDUPDATE = 32;
|
|
|
|
|
- USBASP_CAP_6_UART = 64;
|
|
|
|
|
- USBASP_CAP_7_HID_UART = 128;
|
|
|
|
|
-
|
|
|
|
|
- USBASP_NO_CAPS = (-4);
|
|
|
|
|
-
|
|
|
|
|
- USBASP_CAP_12MHZ_CLOCK = 0;
|
|
|
|
|
- USBASP_CAP_16MHZ_CLOCK = 1;
|
|
|
|
|
- USBASP_CAP_18MHZ_CLOCK = 2;
|
|
|
|
|
- USBASP_CAP_20MHZ_CLOCK = 3;
|
|
|
|
|
-
|
|
|
|
|
- PROG_STATE_IDLE = 0;
|
|
|
|
|
- PROG_STATE_WRITEFLASH = 1;
|
|
|
|
|
- PROG_STATE_READFLASH = 2;
|
|
|
|
|
- PROG_STATE_READEEPROM = 3;
|
|
|
|
|
- PROG_STATE_WRITEEEPROM = 4;
|
|
|
|
|
- PROG_STATE_TPI_READ = 5;
|
|
|
|
|
- PROG_STATE_TPI_WRITE = 6;
|
|
|
|
|
- PROG_STATE_SET_REPORT = 7;
|
|
|
|
|
-
|
|
|
|
|
- UART_STATE_ENABLED = 16;
|
|
|
|
|
- UART_STATE_DISABLED = 0;
|
|
|
|
|
|
|
|
|
|
// USBasp UART Extension
|
|
// USBasp UART Extension
|
|
|
// https://github.com/dioannidis/usbasp/blob/master/firmware/usbasp.h
|
|
// https://github.com/dioannidis/usbasp/blob/master/firmware/usbasp.h
|
|
@@ -99,41 +70,42 @@ const
|
|
|
|
|
|
|
|
type
|
|
type
|
|
|
|
|
|
|
|
|
|
+ TUARTReceive = procedure(Sender: TObject; ASerialData: TByteArray;
|
|
|
|
|
+ ASerialDataLength: SizeInt) of object;
|
|
|
|
|
+
|
|
|
|
|
+ TStatusChange = procedure(Sender: TObject) of object;
|
|
|
|
|
+
|
|
|
{ TUSBasp }
|
|
{ TUSBasp }
|
|
|
|
|
|
|
|
TUSBasp = class(TObject)
|
|
TUSBasp = class(TObject)
|
|
|
private
|
|
private
|
|
|
- FUART_HIDDevice, FStatus_HIDDevice: PHidDevice;
|
|
|
|
|
|
|
+ FUART_HIDDevice, FSTATUS_HIDDevice: PHidDevice;
|
|
|
|
|
|
|
|
- FUART_HIDDevicePath, FStatus_HIDDevicePath, FSerial, FManufacturer,
|
|
|
|
|
- FProductName, FHidApiVersionString: string;
|
|
|
|
|
|
|
+ FUART_HIDDevicePath, FSTATUS_HIDDevicePath, FSerial, FManufacturer,
|
|
|
|
|
+ FProductName, FHidApiVersionString: unicodestring;
|
|
|
|
|
|
|
|
FConnected, FHasHIDUart, FHasStatus, FHasPDI, FHasTPI, FHasSNWrite,
|
|
FConnected, FHasHIDUart, FHasStatus, FHasPDI, FHasTPI, FHasSNWrite,
|
|
|
FUARTOpened: boolean;
|
|
FUARTOpened: boolean;
|
|
|
FCrystalOSC: integer;
|
|
FCrystalOSC: integer;
|
|
|
|
|
|
|
|
- FStatus_RxEvent, FStatus_TxEvent, FUART_RxEvent, FUART_TxEvent,
|
|
|
|
|
- FUnpluggedEvent: TEvent;
|
|
|
|
|
|
|
+ FHIDError: string;
|
|
|
|
|
+
|
|
|
|
|
+ FUART_RxBuffer, FUART_TxBuffer, FStatus_RxBuffer: TSPSCRingBuffer;
|
|
|
|
|
|
|
|
- FHidErrorStr: string;
|
|
|
|
|
|
|
+ FUART_RxEvent, FUART_StartRxEvent, FUART_TxEvent, FSTATUS_RxEvent,
|
|
|
|
|
+ FSTATUS_StartRxEvent: TEvent;
|
|
|
|
|
|
|
|
- FUART_RxBuffer, FUART_TxBuffer, FStatus_RxBuffer,
|
|
|
|
|
- FStatus_TxBuffer: TSPSCRingBuffer;
|
|
|
|
|
|
|
+ FUART_RxThread, FUART_TxThread, FSTATUS_RxThread, FThreadSync: TThread;
|
|
|
|
|
|
|
|
- FUART_RxThread: TThread_HID_UART_Rx;
|
|
|
|
|
- FUART_TxThread: TThread_HID_UART_Tx;
|
|
|
|
|
- FStatus_RxThread: TThread_HID_Status_Rx;
|
|
|
|
|
- FStatus_TxThread: TThread_HID_Status_Tx;
|
|
|
|
|
|
|
+ FOnUARTReceive: TUARTReceive;
|
|
|
|
|
+ FOnStatusChange: TStatusChange;
|
|
|
|
|
|
|
|
function HIDEnumerate(const ASerialNumber: string = ''): boolean;
|
|
function HIDEnumerate(const ASerialNumber: string = ''): boolean;
|
|
|
|
|
+ procedure SetOnStatusChange(AValue: TStatusChange);
|
|
|
|
|
+ procedure SetOnUARTReceive(AValue: TUARTReceive);
|
|
|
protected
|
|
protected
|
|
|
- property ReceiveBuffer: TSPSCRingBuffer read FUART_RxBuffer;
|
|
|
|
|
- property ReceiveEvent: TEvent read FUART_RxEvent;
|
|
|
|
|
- property TransmitBuffer: TSPSCRingBuffer read FUART_TxBuffer;
|
|
|
|
|
- property TransmitEvent: TEvent read FUART_TxEvent;
|
|
|
|
|
- property MonitorBuffer: TSPSCRingBuffer read FStatus_RxBuffer;
|
|
|
|
|
- property MonitorEvent: TEvent read FStatus_RxEvent;
|
|
|
|
|
- property DisconnectEvent: TEvent read FUnpluggedEvent;
|
|
|
|
|
|
|
+ procedure DoUARTReceive;
|
|
|
|
|
+ procedure DoStatusChange;
|
|
|
public
|
|
public
|
|
|
constructor Create;
|
|
constructor Create;
|
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
@@ -142,17 +114,251 @@ type
|
|
|
function Disconnect: boolean;
|
|
function Disconnect: boolean;
|
|
|
function UARTOpen(const ABaudRate, ADataBits, AParity, AStopBits: integer): boolean;
|
|
function UARTOpen(const ABaudRate, ADataBits, AParity, AStopBits: integer): boolean;
|
|
|
function UARTClose: boolean;
|
|
function UARTClose: boolean;
|
|
|
- function ChangeSerialNumber(const ASerialNumber: string): integer;
|
|
|
|
|
|
|
+ function ChangeSerialNumber(const ASerialNumber: string): boolean;
|
|
|
|
|
|
|
|
property Connected: boolean read FConnected;
|
|
property Connected: boolean read FConnected;
|
|
|
property UARTOpened: boolean read FUARTOpened;
|
|
property UARTOpened: boolean read FUARTOpened;
|
|
|
- property HidApiVersion: string read FHidApiVersionString;
|
|
|
|
|
|
|
+ property HidApiVersion: unicodestring read FHidApiVersionString;
|
|
|
|
|
+
|
|
|
|
|
+ property OnUARTReceive: TUARTReceive read FOnUARTReceive write SetOnUARTReceive;
|
|
|
|
|
+ property OnStatusChange: TStatusChange read FOnStatusChange write SetOnStatusChange;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+var
|
|
|
|
|
+ UART_IO_Lock: TCriticalSection;
|
|
|
|
|
+ STATUS_IO_Lock: TCriticalSection;
|
|
|
|
|
+
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
|
|
|
|
+const
|
|
|
|
|
+ USBASP_SHARED_VID = $16C0;
|
|
|
|
|
+ USBASP_SHARED_PID = $05DC;
|
|
|
|
|
+
|
|
|
|
|
+ USBASP_FUNC_GETCAPABILITIES = 127;
|
|
|
|
|
+
|
|
|
|
|
+ USBASP_CAP_0_TPI = 1;
|
|
|
|
|
+ USBASP_CAP_PDI = 16;
|
|
|
|
|
+ USBASP_CAP_2_SNHIDUPDATE = 32;
|
|
|
|
|
+ USBASP_CAP_6_UART = 64;
|
|
|
|
|
+ USBASP_CAP_7_HID_UART = 128;
|
|
|
|
|
+
|
|
|
|
|
+ USBASP_NO_CAPS = (-4);
|
|
|
|
|
+
|
|
|
|
|
+ USBASP_CAP_12MHZ_CLOCK = 0;
|
|
|
|
|
+ USBASP_CAP_16MHZ_CLOCK = 1;
|
|
|
|
|
+ USBASP_CAP_18MHZ_CLOCK = 2;
|
|
|
|
|
+ USBASP_CAP_20MHZ_CLOCK = 3;
|
|
|
|
|
+
|
|
|
|
|
+ PROG_STATE_IDLE = 0;
|
|
|
|
|
+ PROG_STATE_WRITEFLASH = 1;
|
|
|
|
|
+ PROG_STATE_READFLASH = 2;
|
|
|
|
|
+ PROG_STATE_READEEPROM = 3;
|
|
|
|
|
+ PROG_STATE_WRITEEEPROM = 4;
|
|
|
|
|
+ PROG_STATE_TPI_READ = 5;
|
|
|
|
|
+ PROG_STATE_TPI_WRITE = 6;
|
|
|
|
|
+ PROG_STATE_SET_REPORT = 7;
|
|
|
|
|
+
|
|
|
|
|
+ UART_STATE_ENABLED = 16;
|
|
|
|
|
+ UART_STATE_DISABLED = 0;
|
|
|
|
|
+
|
|
|
|
|
+type
|
|
|
|
|
+ THIDPacket_Rx = array[0..7] of byte;
|
|
|
|
|
+ THIDPacket_Tx = array[0..8] of byte;
|
|
|
|
|
+
|
|
|
|
|
+ { TThreadHID }
|
|
|
|
|
+
|
|
|
|
|
+ TThreadHID = class(TThread)
|
|
|
|
|
+ protected
|
|
|
|
|
+ FUSBasp: TUSBasp;
|
|
|
|
|
+ FHIDIOLock: TCriticalSection;
|
|
|
|
|
+ public
|
|
|
|
|
+ constructor Create(const AUSBasp: TUSBasp; const AHIDIOLock: TCriticalSection);
|
|
|
|
|
+ reintroduce;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ { THIDStatus_Rx }
|
|
|
|
|
+
|
|
|
|
|
+ THIDStatus_Rx = class(TThreadHID)
|
|
|
|
|
+ protected
|
|
|
|
|
+ procedure Execute; override;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ { THIDUART_Rx }
|
|
|
|
|
+
|
|
|
|
|
+ THIDUART_Rx = class(TThreadHID)
|
|
|
|
|
+ procedure Execute; override;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ { THIDUART_Tx }
|
|
|
|
|
+
|
|
|
|
|
+ THIDUART_Tx = class(TThreadHID)
|
|
|
|
|
+ protected
|
|
|
|
|
+ procedure Execute; override;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+{ TThreadHID }
|
|
|
|
|
+
|
|
|
|
|
+constructor TThreadHID.Create(const AUSBasp: TUSBasp;
|
|
|
|
|
+ const AHIDIOLock: TCriticalSection);
|
|
|
|
|
+begin
|
|
|
|
|
+ FUSBasp := AUSBasp;
|
|
|
|
|
+ FHIDIOLock := AHIDIOLock;
|
|
|
|
|
+ inherited Create(False);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+{ THIDStatus_Rx }
|
|
|
|
|
+
|
|
|
|
|
+procedure THIDStatus_Rx.Execute;
|
|
|
|
|
+var
|
|
|
|
|
+ HidPacket, PrevHidPacket: THIDPacket_Rx;
|
|
|
|
|
+ DataCount: SizeInt = 0;
|
|
|
|
|
+
|
|
|
|
|
+ function HIDPacketEqual(constref AHIDPacket, APrevHIDPacket:
|
|
|
|
|
+ THIDPacket_Rx): boolean;
|
|
|
|
|
+ var
|
|
|
|
|
+ Idx: byte;
|
|
|
|
|
+ begin
|
|
|
|
|
+ Result := True;
|
|
|
|
|
+ for idx := Low(AHidPacket) to High(AHIDPacket) do
|
|
|
|
|
+ if APrevHIDPacket[Idx] <> AHIDPacket[Idx] then
|
|
|
|
|
+ begin
|
|
|
|
|
+ Result := False;
|
|
|
|
|
+ Break;
|
|
|
|
|
+ end;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+begin
|
|
|
|
|
+ FillChar(HIDPacket, High(THIDPacket_Rx) + 1, 0);
|
|
|
|
|
+ PrevHidPacket := HidPacket;
|
|
|
|
|
+
|
|
|
|
|
+ repeat
|
|
|
|
|
+ FUSBasp.FSTATUS_StartRxEvent.WaitFor(INFINITE);
|
|
|
|
|
+
|
|
|
|
|
+ FHIDIOLock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ if Assigned(FUSBasp.FSTATUS_HIDDevice) then
|
|
|
|
|
+ DataCount := FUSBasp.FSTATUS_HIDDevice^.ReadTimeout(HIDPacket,
|
|
|
|
|
+ High(HIDPacket) + 1, 5)
|
|
|
|
|
+ else
|
|
|
|
|
+ DataCount := 0;
|
|
|
|
|
+ finally
|
|
|
|
|
+ FHIDIOLock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ if (DataCount > 0) and (not HIDPacketEqual(HIDPacket, PrevHidPacket)) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ PrevHidPacket := HidPacket;
|
|
|
|
|
+ FUSBasp.FStatus_RxBuffer.Write(HIDPacket, DataCount);
|
|
|
|
|
+ FUSBasp.FSTATUS_RxEvent.SetEvent;
|
|
|
|
|
+ end;
|
|
|
|
|
+ until Terminated;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+{ THIDUART_Rx }
|
|
|
|
|
+
|
|
|
|
|
+procedure THIDUART_Rx.Execute;
|
|
|
|
|
+var
|
|
|
|
|
+ HIDPacket: THIDPacket_Rx;
|
|
|
|
|
+ SerialDataCount, DataCount: byte;
|
|
|
|
|
+begin
|
|
|
|
|
+ FillChar(HIDPacket, High(THIDPacket_Rx) + 1, 0);
|
|
|
|
|
+
|
|
|
|
|
+ repeat
|
|
|
|
|
+ FUSBasp.FUART_StartRxEvent.WaitFor(INFINITE);
|
|
|
|
|
+
|
|
|
|
|
+ FHIDIOLock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ if Assigned(FUSBasp.FUART_HIDDevice) then
|
|
|
|
|
+ DataCount := FUSBasp.FUART_HIDDevice^.ReadTimeout(HIDPacket,
|
|
|
|
|
+ High(THIDPacket_Rx) + 1, 5)
|
|
|
|
|
+ else
|
|
|
|
|
+ DataCount := 0;
|
|
|
|
|
+ finally
|
|
|
|
|
+ FHIDIOLock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ if (DataCount > 0) and (HIDPacket[7] > 0) then
|
|
|
|
|
+ begin
|
|
|
|
|
+ if (HIDPacket[7] > 7) then
|
|
|
|
|
+ SerialDataCount := 8
|
|
|
|
|
+ else
|
|
|
|
|
+ SerialDataCount := HIDPacket[7];
|
|
|
|
|
+ if FUSBasp.FUART_RxBuffer.Write(HIDPacket, SerialDataCount) <>
|
|
|
|
|
+ SerialDataCount then
|
|
|
|
|
+ raise TExceptionClass.Create('Receive Buffer OverRun');
|
|
|
|
|
+ FUSBasp.FUART_RxEvent.SetEvent;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ until Terminated;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+{ THIDUART_Tx }
|
|
|
|
|
+
|
|
|
|
|
+procedure THIDUART_Tx.Execute;
|
|
|
|
|
+var
|
|
|
|
|
+ HIDPacket: THIDPacket_Tx;
|
|
|
|
|
+ SerialCountOrDataByte, DataCount: byte;
|
|
|
|
|
+begin
|
|
|
|
|
+ FillChar(HIDPacket, High(HIDPacket) + 1, 0);
|
|
|
|
|
+ repeat
|
|
|
|
|
+ if FUSBAsp.FUART_TxBuffer.Empty then
|
|
|
|
|
+ FUSBasp.FUART_TxEvent.ResetEvent;
|
|
|
|
|
+
|
|
|
|
|
+ FUSBasp.FUART_TxEvent.WaitFor(INFINITE);
|
|
|
|
|
+
|
|
|
|
|
+ DataCount := FUSBAsp.FUART_TxBuffer.Peek(HIDPacket[1], 8);
|
|
|
|
|
+ SerialCountOrDataByte := DataCount;
|
|
|
|
|
+
|
|
|
|
|
+ if (SerialCountOrDataByte = 8) and (HIDPacket[8] = 7) then
|
|
|
|
|
+ SerialCountOrDataByte := 7
|
|
|
|
|
+ else
|
|
|
|
|
+ if SerialCountOrDataByte < 8 then
|
|
|
|
|
+ HIDPacket[8] := SerialCountOrDataByte;
|
|
|
|
|
+
|
|
|
|
|
+ if DataCount > 0 then
|
|
|
|
|
+ begin
|
|
|
|
|
+ FHIDIOLock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ if Assigned(FUSBasp.FUART_HIDDevice) then
|
|
|
|
|
+ SerialCountOrDataByte :=
|
|
|
|
|
+ FUSBasp.FUART_HIDDevice^.Write(HIDPacket, High(HIDPacket) + 1);
|
|
|
|
|
+ finally
|
|
|
|
|
+ FHIDIOLock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
+ FUSBAsp.FUART_TxBuffer.AdvanceReadIdx(DataCount);
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+ until Terminated;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
type
|
|
type
|
|
|
- TUSBPacketBuffer = array[0..8] of byte;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ { TThreadSync }
|
|
|
|
|
+
|
|
|
|
|
+ TThreadSync = class(TThread)
|
|
|
|
|
+ private
|
|
|
|
|
+ FUSBasp: TUSBasp;
|
|
|
|
|
+ protected
|
|
|
|
|
+ procedure Execute; override;
|
|
|
|
|
+ public
|
|
|
|
|
+ constructor Create(const AUSBasp: TUSBasp); reintroduce;
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TThreadSync.Execute;
|
|
|
|
|
+begin
|
|
|
|
|
+ repeat
|
|
|
|
|
+ if FUSBasp.FUART_RxEvent.WaitFor(3) = wrSignaled then
|
|
|
|
|
+ Synchronize(@FUSBasp.DoUARTReceive);
|
|
|
|
|
+ if FUSBasp.FSTATUS_RxEvent.WaitFor(3) = wrSignaled then
|
|
|
|
|
+ Synchronize(@FUSBasp.DoStatusChange);
|
|
|
|
|
+ until Terminated;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+constructor TThreadSync.Create(const AUSBasp: TUSBasp);
|
|
|
|
|
+begin
|
|
|
|
|
+ FUSBasp := AUSBasp;
|
|
|
|
|
+ inherited Create(False);
|
|
|
|
|
+end;
|
|
|
|
|
|
|
|
{ TUSBasp }
|
|
{ TUSBasp }
|
|
|
|
|
|
|
@@ -162,24 +368,28 @@ begin
|
|
|
FUARTOpened := False;
|
|
FUARTOpened := False;
|
|
|
FSerial := '';
|
|
FSerial := '';
|
|
|
|
|
|
|
|
- FUART_RxBuffer := TSPSCRingBuffer.Create(1024);
|
|
|
|
|
- FUART_TxBuffer := TSPSCRingBuffer.Create(1024);
|
|
|
|
|
- FStatus_RxBuffer := TSPSCRingBuffer.Create(1024);
|
|
|
|
|
- FStatus_TxBuffer := TSPSCRingBuffer.Create(1024);
|
|
|
|
|
|
|
+ FUART_RxBuffer := TSPSCRingBuffer.Create(8192);
|
|
|
|
|
+ FUART_TxBuffer := TSPSCRingBuffer.Create(8192);
|
|
|
|
|
+ FStatus_RxBuffer := TSPSCRingBuffer.Create(8);
|
|
|
|
|
|
|
|
Randomize;
|
|
Randomize;
|
|
|
- FUART_RxEvent := TEvent.Create(nil, False, False, 'UARTRX_' + IntToStr(Random(999)));
|
|
|
|
|
- FUART_TxEvent := TEvent.Create(nil, True, False, 'UARTTX_' + IntToStr(Random(999)));
|
|
|
|
|
|
|
|
|
|
- FStatus_RxEvent := TEvent.Create(nil, False, False, 'STUSRX_' +
|
|
|
|
|
- IntToStr(Random(999)));
|
|
|
|
|
- FStatus_TxEvent := TEvent.Create(nil, True, False, 'STUSTX_' +
|
|
|
|
|
|
|
+ FUART_StartRxEvent := TEvent.Create(nil, True, False, 'STARTUARTRX' +
|
|
|
IntToStr(Random(999)));
|
|
IntToStr(Random(999)));
|
|
|
|
|
+ FUART_RxEvent := TEvent.Create(nil, False, False, 'UARTRX' + IntToStr(Random(999)));
|
|
|
|
|
+ FUART_TxEvent := TEvent.Create(nil, True, False, 'UARTTX' + IntToStr(Random(999)));
|
|
|
|
|
|
|
|
- FUnpluggedEvent := TEvent.Create(nil, False, False, 'UNPLD_' +
|
|
|
|
|
|
|
+ FSTATUS_RxEvent := TEvent.Create(nil, False, False, 'STATUSRX' +
|
|
|
|
|
+ IntToStr(Random(999)));
|
|
|
|
|
+ FSTATUS_StartRxEvent := TEvent.Create(nil, True, False, 'STARTSTATUSRX' +
|
|
|
IntToStr(Random(999)));
|
|
IntToStr(Random(999)));
|
|
|
|
|
|
|
|
- HidInit();
|
|
|
|
|
|
|
+ FThreadSync := TThreadSync.Create(Self);
|
|
|
|
|
+
|
|
|
|
|
+ FUART_RxThread := THIDUART_Rx.Create(Self, UART_IO_Lock);
|
|
|
|
|
+ FUART_TxThread := THIDUART_Tx.Create(Self, UART_IO_Lock);
|
|
|
|
|
+
|
|
|
|
|
+ FSTATUS_RxThread := THIDStatus_Rx.Create(Self, STATUS_IO_Lock);
|
|
|
|
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -187,63 +397,73 @@ destructor TUSBasp.Destroy;
|
|
|
begin
|
|
begin
|
|
|
Disconnect;
|
|
Disconnect;
|
|
|
|
|
|
|
|
|
|
+ FThreadSync.Terminate;
|
|
|
|
|
+ FThreadSync.WaitFor;
|
|
|
|
|
+ FreeAndNil(FThreadSync);
|
|
|
|
|
+
|
|
|
|
|
+ FUART_RxThread.Terminate;
|
|
|
|
|
+ FUART_StartRxEvent.SetEvent;
|
|
|
|
|
+ FUART_RxThread.WaitFor;
|
|
|
|
|
+ FreeAndNil(FUART_RxThread);
|
|
|
|
|
+
|
|
|
|
|
+ FUART_TxThread.Terminate;
|
|
|
|
|
+ FUART_TxEvent.SetEvent;
|
|
|
|
|
+ FUART_TxThread.WaitFor;
|
|
|
|
|
+ FreeAndNil(FUART_TxThread);
|
|
|
|
|
+
|
|
|
|
|
+ FSTATUS_RxThread.Terminate;
|
|
|
|
|
+ FSTATUS_StartRxEvent.SetEvent;
|
|
|
|
|
+ FSTATUS_RxThread.WaitFor;
|
|
|
|
|
+ FreeAndNil(FSTATUS_RxThread);
|
|
|
|
|
+
|
|
|
FreeAndNil(FUART_RxBuffer);
|
|
FreeAndNil(FUART_RxBuffer);
|
|
|
FreeAndNil(FUART_TxBuffer);
|
|
FreeAndNil(FUART_TxBuffer);
|
|
|
FreeAndNil(FStatus_RxBuffer);
|
|
FreeAndNil(FStatus_RxBuffer);
|
|
|
- FreeAndNil(FStatus_TxBuffer);
|
|
|
|
|
|
|
|
|
|
- FUART_RxEvent.Free;
|
|
|
|
|
- FUART_TxEvent.Free;
|
|
|
|
|
- FStatus_RxEvent.Free;
|
|
|
|
|
- FStatus_TxEvent.Free;
|
|
|
|
|
- FUnpluggedEvent.Free;
|
|
|
|
|
|
|
+ FreeAndNil(FUART_RxEvent);
|
|
|
|
|
+ FreeAndNil(FUART_TxEvent);
|
|
|
|
|
+ FreeAndNil(FSTATUS_RxEvent);
|
|
|
|
|
|
|
|
- HidExit();
|
|
|
|
|
|
|
+ FreeAndNil(FUART_StartRxEvent);
|
|
|
|
|
+ FreeAndNil(FSTATUS_StartRxEvent);
|
|
|
|
|
|
|
|
inherited Destroy;
|
|
inherited Destroy;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
function TUSBasp.Connect(const ASerialNumber: string = ''): boolean;
|
|
function TUSBasp.Connect(const ASerialNumber: string = ''): boolean;
|
|
|
begin
|
|
begin
|
|
|
- FConnected := False;
|
|
|
|
|
if not FConnected then
|
|
if not FConnected then
|
|
|
begin
|
|
begin
|
|
|
|
|
|
|
|
|
|
+ HidInit();
|
|
|
|
|
+
|
|
|
if not HIDEnumerate(ASerialNumber) then
|
|
if not HIDEnumerate(ASerialNumber) then
|
|
|
Exit;
|
|
Exit;
|
|
|
|
|
|
|
|
FUART_HIDDevice := THidDevice.OpenPath(FUART_HIDDevicePath);
|
|
FUART_HIDDevice := THidDevice.OpenPath(FUART_HIDDevicePath);
|
|
|
- FHidErrorStr := FUART_HIDDevice^.GetError;
|
|
|
|
|
|
|
+ FHIDError := THIDDevice.GetNullError(FUART_HIDDevice);
|
|
|
|
|
|
|
|
- if FHidErrorStr <> 'Success' then
|
|
|
|
|
|
|
+ if (FHIDError <> 'Success') then
|
|
|
Exit;
|
|
Exit;
|
|
|
|
|
|
|
|
- FUART_HIDDevice^.SetNonBlocking(0);
|
|
|
|
|
-
|
|
|
|
|
- FUART_RxThread := TThread_HID_UART_Rx.Create(
|
|
|
|
|
- FUART_HIDDevice, FUART_RxBuffer, FUART_RxEvent, FUnpluggedEvent);
|
|
|
|
|
- FUART_TxThread := TThread_HID_UART_Tx.Create(
|
|
|
|
|
- FUART_HIDDevice, FUART_TxBuffer, FUART_TxEvent, FUnpluggedEvent);
|
|
|
|
|
|
|
+ FUART_HIDDevice^.SetNonBlocking(1);
|
|
|
|
|
|
|
|
if FHasStatus then
|
|
if FHasStatus then
|
|
|
begin
|
|
begin
|
|
|
- FStatus_HIDDevice := THidDevice.OpenPath(FStatus_HIDDevicePath);
|
|
|
|
|
- FHidErrorStr := FStatus_HIDDevice^.GetError;
|
|
|
|
|
|
|
+ FSTATUS_HIDDevice := THidDevice.OpenPath(FSTATUS_HIDDevicePath);
|
|
|
|
|
+ FHIDError := THIDDevice.GetNullError(FSTATUS_HIDDevice);
|
|
|
|
|
|
|
|
- if FHidErrorStr = 'Success' then
|
|
|
|
|
|
|
+ if (FHIDError = 'Success') then
|
|
|
begin
|
|
begin
|
|
|
- FStatus_HIDDevice^.SetNonBlocking(0);
|
|
|
|
|
-
|
|
|
|
|
- FStatus_RxThread := TThread_HID_Status_Rx.Create(FStatus_HIDDevice,
|
|
|
|
|
- FStatus_RxBuffer, FStatus_RxEvent, FUnpluggedEvent);
|
|
|
|
|
-
|
|
|
|
|
- FStatus_TxThread := TThread_HID_Status_Tx.Create(FStatus_HIDDevice,
|
|
|
|
|
- FStatus_TxBuffer, FStatus_TxEvent, FUnpluggedEvent);
|
|
|
|
|
|
|
+ FSTATUS_HIDDevice^.SetNonBlocking(1);
|
|
|
|
|
+ FSTATUS_StartRxEvent.SetEvent;
|
|
|
end;
|
|
end;
|
|
|
|
|
+
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
FConnected := True;
|
|
FConnected := True;
|
|
|
end;
|
|
end;
|
|
|
|
|
+
|
|
|
Result := FConnected;
|
|
Result := FConnected;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -251,57 +471,68 @@ function TUSBasp.Disconnect: boolean;
|
|
|
begin
|
|
begin
|
|
|
if FConnected then
|
|
if FConnected then
|
|
|
begin
|
|
begin
|
|
|
|
|
+
|
|
|
if FUARTOpened then
|
|
if FUARTOpened then
|
|
|
|
|
+ begin
|
|
|
UARTClose;
|
|
UARTClose;
|
|
|
|
|
+ Sleep(100);
|
|
|
|
|
+ end;
|
|
|
|
|
|
|
|
- FUART_RxThread.Terminate;
|
|
|
|
|
- FUART_RxThread.WaitFor;
|
|
|
|
|
- FreeAndNil(FUART_RxThread);
|
|
|
|
|
-
|
|
|
|
|
- FUART_TxThread.Terminate;
|
|
|
|
|
- FUART_TxEvent.SetEvent;
|
|
|
|
|
- FUART_TxThread.WaitFor;
|
|
|
|
|
- FreeAndNil(FUART_TxThread);
|
|
|
|
|
-
|
|
|
|
|
- FUART_HIDDevice^.Close;
|
|
|
|
|
- FUART_HIDDevice := nil;
|
|
|
|
|
|
|
+ UART_IO_Lock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ FUART_HIDDevice^.Close;
|
|
|
|
|
+ FUART_HIDDevice := nil;
|
|
|
|
|
+ finally
|
|
|
|
|
+ UART_IO_Lock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
|
|
|
if FHasStatus then
|
|
if FHasStatus then
|
|
|
begin
|
|
begin
|
|
|
- FStatus_RxThread.Terminate;
|
|
|
|
|
- FStatus_RxThread.WaitFor;
|
|
|
|
|
- FreeAndNil(FStatus_RxThread);
|
|
|
|
|
-
|
|
|
|
|
- FStatus_TxThread.Terminate;
|
|
|
|
|
- FStatus_TxEvent.SetEvent;
|
|
|
|
|
- FStatus_TxThread.WaitFor;
|
|
|
|
|
- FreeAndNil(FStatus_TxThread);
|
|
|
|
|
-
|
|
|
|
|
- FStatus_HIDDevice^.Close;
|
|
|
|
|
- FStatus_HIDDevice := nil;
|
|
|
|
|
|
|
+ STATUS_IO_Lock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ FSTATUS_HIDDevice^.Close;
|
|
|
|
|
+ FSTATUS_HIDDevice := nil;
|
|
|
|
|
+ FSTATUS_StartRxEvent.ResetEvent;
|
|
|
|
|
+ finally
|
|
|
|
|
+ STATUS_IO_Lock.Release;
|
|
|
|
|
+ end;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
FConnected := False;
|
|
FConnected := False;
|
|
|
|
|
+
|
|
|
|
|
+ HidExit;
|
|
|
|
|
+
|
|
|
end;
|
|
end;
|
|
|
- Result := FConnected;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ Result := not FConnected;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
function TUSBasp.UARTOpen(const ABaudRate, ADataBits, AParity,
|
|
function TUSBasp.UARTOpen(const ABaudRate, ADataBits, AParity,
|
|
|
AStopBits: integer): boolean;
|
|
AStopBits: integer): boolean;
|
|
|
var
|
|
var
|
|
|
- Buffer: TUSBPacketBuffer;
|
|
|
|
|
|
|
+ HIDPacket: THIDPacket_Tx;
|
|
|
Prescaler: word;
|
|
Prescaler: word;
|
|
|
|
|
+ Rslt: SizeInt;
|
|
|
begin
|
|
begin
|
|
|
if FConnected and not FUARTOpened then
|
|
if FConnected and not FUARTOpened then
|
|
|
begin
|
|
begin
|
|
|
Prescaler := FCrystalOsc div 8 div ABaudRate - 1;
|
|
Prescaler := FCrystalOsc div 8 div ABaudRate - 1;
|
|
|
|
|
|
|
|
- Buffer[0] := 0;
|
|
|
|
|
- Buffer[1] := lo(Prescaler);
|
|
|
|
|
- Buffer[2] := hi(Prescaler);
|
|
|
|
|
- Buffer[3] := ADataBits or AStopBits or AParity;
|
|
|
|
|
|
|
+ Fillchar(HIDPacket, High(HIDPacket) + 1, 0);
|
|
|
|
|
+ HIDPacket[0] := 0;
|
|
|
|
|
+ HIDPacket[1] := lo(Prescaler);
|
|
|
|
|
+ HIDPacket[2] := hi(Prescaler);
|
|
|
|
|
+ HIDPacket[3] := ADataBits or AStopBits or AParity;
|
|
|
|
|
+
|
|
|
|
|
+ UART_IO_Lock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ Rslt := FUART_HIDDevice^.SendFeatureReport(HIDPacket, High(HIDPacket) + 1);
|
|
|
|
|
+ FUART_StartRxEvent.SetEvent;
|
|
|
|
|
+ finally
|
|
|
|
|
+ UART_IO_Lock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
|
|
|
- if FUART_HIDDevice^.SendFeatureReport(Buffer, 8 + 1) > 0 then
|
|
|
|
|
|
|
+ if Rslt > 0 then
|
|
|
FUARTOpened := True;
|
|
FUARTOpened := True;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
@@ -310,37 +541,49 @@ end;
|
|
|
|
|
|
|
|
function TUSBasp.UARTClose: boolean;
|
|
function TUSBasp.UARTClose: boolean;
|
|
|
var
|
|
var
|
|
|
- Buffer: TUSBPacketBuffer;
|
|
|
|
|
|
|
+ HIDPacket: THIDPacket_Tx;
|
|
|
|
|
+ Rslt: SizeInt;
|
|
|
begin
|
|
begin
|
|
|
if FConnected and FUARTOpened then
|
|
if FConnected and FUARTOpened then
|
|
|
begin
|
|
begin
|
|
|
|
|
+ Fillchar(HIDPacket, High(HIDPacket) + 1, 0);
|
|
|
|
|
+ HIDPacket[0] := 0;
|
|
|
|
|
+ HIDPacket[1] := 0;
|
|
|
|
|
+ HIDPacket[2] := 0;
|
|
|
|
|
+ HIDPacket[3] := 0;
|
|
|
|
|
+ HIDPacket[4] := 0;
|
|
|
|
|
+
|
|
|
|
|
+ UART_IO_Lock.Acquire;
|
|
|
|
|
+ try
|
|
|
|
|
+ Rslt := FUART_HIDDevice^.SendFeatureReport(HIDPacket, High(HIDPacket) + 1);
|
|
|
|
|
+ FUART_StartRxEvent.ResetEvent;
|
|
|
|
|
+ finally
|
|
|
|
|
+ UART_IO_Lock.Release;
|
|
|
|
|
+ end;
|
|
|
|
|
|
|
|
- Buffer[0] := 0;
|
|
|
|
|
- Buffer[1] := 0;
|
|
|
|
|
- Buffer[2] := 0;
|
|
|
|
|
- Buffer[3] := 0;
|
|
|
|
|
-
|
|
|
|
|
- FUART_HIDDevice^.SendFeatureReport(Buffer, 8 + 1);
|
|
|
|
|
-
|
|
|
|
|
- FUARTOpened := False;
|
|
|
|
|
|
|
+ if Rslt > 0 then
|
|
|
|
|
+ FUARTOpened := False;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
- Result := FUARTOpened;
|
|
|
|
|
|
|
+ Result := not FUARTOpened;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
function TUSBasp.HIDEnumerate(const ASerialNumber: string): boolean;
|
|
function TUSBasp.HIDEnumerate(const ASerialNumber: string): boolean;
|
|
|
var
|
|
var
|
|
|
HidItemRoot, HidItem: PHidDeviceInfo;
|
|
HidItemRoot, HidItem: PHidDeviceInfo;
|
|
|
|
|
+ HIDDevice: PHidDevice;
|
|
|
HIDDeviceMatch: boolean;
|
|
HIDDeviceMatch: boolean;
|
|
|
- FeatureReportBuffer: TUSBPacketBuffer;
|
|
|
|
|
|
|
+ FeatureReportBuffer: THIDPacket_Rx;
|
|
|
begin
|
|
begin
|
|
|
Result := False;
|
|
Result := False;
|
|
|
|
|
|
|
|
|
|
+ FUART_HIDDevice := nil;
|
|
|
|
|
+ FSTATUS_HIDDevice := nil;
|
|
|
|
|
+
|
|
|
FUART_HIDDevicePath := '';
|
|
FUART_HIDDevicePath := '';
|
|
|
- FStatus_HIDDevicePath := '';
|
|
|
|
|
|
|
+ FSTATUS_HIDDevicePath := '';
|
|
|
|
|
|
|
|
- FUART_HIDDevice := nil;
|
|
|
|
|
- FStatus_HIDDevice := nil;
|
|
|
|
|
|
|
+ FHasStatus := False;
|
|
|
|
|
|
|
|
try
|
|
try
|
|
|
HidItemRoot := THidDeviceInfo.Enumerate(USBASP_SHARED_VID, USBASP_SHARED_PID);
|
|
HidItemRoot := THidDeviceInfo.Enumerate(USBASP_SHARED_VID, USBASP_SHARED_PID);
|
|
@@ -361,7 +604,7 @@ begin
|
|
|
Result := True;
|
|
Result := True;
|
|
|
end;
|
|
end;
|
|
|
2: begin
|
|
2: begin
|
|
|
- FStatus_HIDDevicePath := HidItem^.Path;
|
|
|
|
|
|
|
+ FSTATUS_HIDDevicePath := HidItem^.Path;
|
|
|
FHasStatus := True;
|
|
FHasStatus := True;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
@@ -374,13 +617,13 @@ begin
|
|
|
|
|
|
|
|
if Result then
|
|
if Result then
|
|
|
begin
|
|
begin
|
|
|
- FUART_HIDDevice := THidDevice.OpenPath(FUART_HIDDevicePath);
|
|
|
|
|
|
|
+ HIDDevice := THidDevice.OpenPath(FUART_HIDDevicePath);
|
|
|
|
|
|
|
|
- FSerial := FUART_HIDDevice^.GetSerialNumberString;
|
|
|
|
|
- FManufacturer := FUART_HIDDevice^.GetManufacturerString;
|
|
|
|
|
- FProductName := FUART_HIDDevice^.GetProductString;
|
|
|
|
|
|
|
+ FSerial := HIDDevice^.GetSerialNumberString;
|
|
|
|
|
+ FManufacturer := HIDDevice^.GetManufacturerString;
|
|
|
|
|
+ FProductName := HIDDevice^.GetProductString;
|
|
|
|
|
|
|
|
- if FUART_HIDDevice^.GetFeatureReport(FeatureReportBuffer, 8 + 1) > 0 then
|
|
|
|
|
|
|
+ if HIDDevice^.GetFeatureReport(FeatureReportBuffer, 8 + 1) > 0 then
|
|
|
begin
|
|
begin
|
|
|
|
|
|
|
|
case FeatureReportBuffer[6] of
|
|
case FeatureReportBuffer[6] of
|
|
@@ -399,18 +642,62 @@ begin
|
|
|
|
|
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
- FUART_HIDDevice^.Close;
|
|
|
|
|
- FUART_HIDDevice := nil;
|
|
|
|
|
|
|
+ HIDDevice^.Close;
|
|
|
|
|
+ HIDDevice := nil;
|
|
|
|
|
+
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
-function TUSBasp.ChangeSerialNumber(const ASerialNumber: string): integer;
|
|
|
|
|
|
|
+procedure TUSBasp.DoUARTReceive;
|
|
|
var
|
|
var
|
|
|
- Buffer: TUSBPacketBuffer;
|
|
|
|
|
|
|
+ SerialData: TByteArray;
|
|
|
|
|
+ SerialDataLength, CRIdx: SizeInt;
|
|
|
|
|
+begin
|
|
|
|
|
+ repeat
|
|
|
|
|
+ SerialDataLength := FUART_RxBuffer.Peek(SerialData, FUART_RxBuffer.Size);
|
|
|
|
|
+
|
|
|
|
|
+ CRIdx := IndexByte(SerialData, SerialDataLength, Ord(#10));
|
|
|
|
|
+ if (CRIdx > 0) and (SerialData[CRIdx - 1] = Ord(#13)) then
|
|
|
|
|
+ FUART_RxBuffer.AdvanceReadIdx(CRIdx + 1);
|
|
|
|
|
+
|
|
|
|
|
+ if Assigned(FOnUARTReceive) and (CRIdx - 1 > 0) then
|
|
|
|
|
+ FOnUARTReceive(Self, SerialData, CRIdx - 1);
|
|
|
|
|
+ until CRIdx = -1;
|
|
|
|
|
+
|
|
|
|
|
+ //SerialDataLength := FUART_RxBuffer.Read(SerialData, FUART_RxBuffer.Size);
|
|
|
|
|
+ //if Assigned(FOnUARTReceive) then
|
|
|
|
|
+ // FOnUARTReceive(Self, SerialData, SerialDataLength);
|
|
|
|
|
+
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TUSBasp.SetOnUARTReceive(AValue: TUARTReceive);
|
|
|
|
|
+begin
|
|
|
|
|
+ if FOnUARTReceive = AValue then Exit;
|
|
|
|
|
+ FOnUARTReceive := AValue;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TUSBasp.DoStatusChange;
|
|
|
|
|
+var
|
|
|
|
|
+ StatusBuffer: TByteArray;
|
|
|
|
|
+begin
|
|
|
|
|
+ FStatus_RxBuffer.Read(StatusBuffer, FStatus_RxBuffer.Size);
|
|
|
|
|
+ if Assigned(FOnStatusChange) then
|
|
|
|
|
+ FOnStatusChange(Self);
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+procedure TUSBasp.SetOnStatusChange(AValue: TStatusChange);
|
|
|
|
|
+begin
|
|
|
|
|
+ if FOnStatusChange = AValue then Exit;
|
|
|
|
|
+ FOnStatusChange := AValue;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+function TUSBasp.ChangeSerialNumber(const ASerialNumber: string): boolean;
|
|
|
|
|
+var
|
|
|
|
|
+ Buffer: THIDPacket_Rx;
|
|
|
ErrorCode: integer;
|
|
ErrorCode: integer;
|
|
|
SerNumValue: word;
|
|
SerNumValue: word;
|
|
|
begin
|
|
begin
|
|
|
- Result := 0;
|
|
|
|
|
|
|
+ Result := False;
|
|
|
if FConnected and not FUARTOpened then
|
|
if FConnected and not FUARTOpened then
|
|
|
begin
|
|
begin
|
|
|
Val(ASerialNumber, SerNumValue, ErrorCode);
|
|
Val(ASerialNumber, SerNumValue, ErrorCode);
|
|
@@ -422,7 +709,17 @@ begin
|
|
|
Buffer[4] := 1;
|
|
Buffer[4] := 1;
|
|
|
|
|
|
|
|
FUART_HIDDevice^.SendFeatureReport(Buffer, 8 + 1);
|
|
FUART_HIDDevice^.SendFeatureReport(Buffer, 8 + 1);
|
|
|
|
|
+ FHIDError := THidDevice.GetNullError();
|
|
|
|
|
+ //Result := FUART_HIDDevice^.GetError = 'Success';
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+initialization
|
|
|
|
|
+ UART_IO_Lock := TCriticalSection.Create;
|
|
|
|
|
+ STATUS_IO_Lock := TCriticalSection.Create;
|
|
|
|
|
+
|
|
|
|
|
+finalization
|
|
|
|
|
+ UART_IO_Lock.Free;
|
|
|
|
|
+ STATUS_IO_Lock.Free;
|
|
|
|
|
+
|
|
|
end.
|
|
end.
|