1
0

usbasp_threads.pas 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. unit USBasp_Threads;
  2. {
  3. This file is part of
  4. Nephelae USBasp HID UART.
  5. USB HID Read / Write threads.
  6. Copyright (C) 2022 - 2025 Dimitrios Chr. Ioannidis.
  7. Nephelae - https://www.nephelae.eu
  8. https://www.nephelae.eu/
  9. Licensed under the MIT License (MIT).
  10. See licence file in root directory.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
  12. ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  13. TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  14. PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
  15. SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
  16. ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  17. ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  19. OTHER DEALINGS IN THE SOFTWARE.
  20. }
  21. {$mode ObjFPC}{$H+}
  22. interface
  23. uses
  24. Classes, SysUtils, syncobjs, hidapi,
  25. SPSCRingBuffer;
  26. type
  27. { TThreadHID_Base }
  28. TThreadHID_Base = class(TThread)
  29. protected
  30. FThreadEvent: TEvent;
  31. FThreadUnpluggedEvent: TEvent;
  32. FBuffer: TSPSCRingBuffer;
  33. FHIDDevice: PHidDevice;
  34. public
  35. constructor Create(const AHIDDevice: PHidDevice;
  36. const ABuffer: TSPSCRingBuffer; const AThreadEvent: TEvent;
  37. const AUnpluggedEvent: TEvent); reintroduce;
  38. end;
  39. { TThread_HID_Status_Rx }
  40. TThread_HID_Status_Rx = class(TThreadHID_Base)
  41. protected
  42. procedure Execute; override;
  43. end;
  44. { TThread_HID_Status_Tx }
  45. TThread_HID_Status_Tx = class(TThreadHID_Base)
  46. protected
  47. procedure Execute; override;
  48. end;
  49. { TThread_HID_UART_Rx }
  50. TThread_HID_UART_Rx = class(TThreadHID_Base)
  51. procedure Execute; override;
  52. end;
  53. { TThread_HID_UART_Tx }
  54. TThread_HID_UART_Tx = class(TThreadHID_Base)
  55. protected
  56. procedure Execute; override;
  57. end;
  58. implementation
  59. { TThreadHID_Base }
  60. constructor TThreadHID_Base.Create(const AHIDDevice: PHidDevice;
  61. const ABuffer: TSPSCRingBuffer; const AThreadEvent: TEvent;
  62. const AUnpluggedEvent: TEvent);
  63. begin
  64. inherited Create(False);
  65. FThreadEvent := AThreadEvent;
  66. FThreadUnpluggedEvent := AUnpluggedEvent;
  67. FBuffer := ABuffer;
  68. FHIDDevice := AHIDDevice;
  69. end;
  70. { TThread_HID_Status_Rx }
  71. procedure TThread_HID_Status_Rx.Execute;
  72. var
  73. USBAspHidPacket: array[0..7] of byte = (0, 0, 0, 0, 0, 0, 0, 0);
  74. DataCount: SizeInt = 0;
  75. begin
  76. repeat
  77. DataCount := FHIDDevice^.Read(USBAspHidPacket, 8);
  78. if DataCount > 0 then
  79. begin
  80. FBuffer.Write(USBAspHidPacket, DataCount);
  81. FThreadEvent.SetEvent;
  82. end;
  83. until Terminated;
  84. end;
  85. { TThread_HID_Status_Tx }
  86. procedure TThread_HID_Status_Tx.Execute;
  87. var
  88. USBAspHidPacket: array[0..8] of byte = (0, 0, 0, 0, 0, 0, 0, 0, 0);
  89. DataCount: byte = 0;
  90. begin
  91. repeat
  92. if FBuffer.Empty then
  93. FThreadEvent.ResetEvent;
  94. FThreadEvent.WaitFor(INFINITE);
  95. FillChar(USBAspHidPacket, 8, 0);
  96. DataCount := FBuffer.Peek(USBAspHidPacket[1], 8);
  97. if DataCount > 0 then
  98. begin
  99. FHIDDevice^.Write(USBAspHidPacket, 8 + 1);
  100. FBuffer.AdvanceReadIdx(DataCount);
  101. end;
  102. until Terminated;
  103. end;
  104. { TThread_HID_UART_Rx }
  105. procedure TThread_HID_UART_Rx.Execute;
  106. var
  107. USBAspHidPacket: array[0..7] of byte = (0, 0, 0, 0, 0, 0, 0, 0);
  108. SerialDataCount, DataCount: byte;
  109. begin
  110. repeat
  111. DataCount := FHIDDevice^.Read(USBAspHidPacket, 8);
  112. if (DataCount > 0) and (USBAspHidPacket[7] > 0) then
  113. begin
  114. if (USBAspHidPacket[7] > 7) then
  115. SerialDataCount := 8
  116. else
  117. SerialDataCount := USBAspHidPacket[7];
  118. if FBuffer.Write(USBAspHidPacket, SerialDataCount) <> SerialDataCount then
  119. raise TExceptionClass.Create('Buffer OverRun');
  120. FThreadEvent.SetEvent;
  121. end;
  122. until Terminated;
  123. end;
  124. { TThread_HID_UART_Tx }
  125. procedure TThread_HID_UART_Tx.Execute;
  126. var
  127. USBAspHidPacket: array[0..8] of byte = (0, 0, 0, 0, 0, 0, 0, 0, 0);
  128. SerialCountOrDataByte, DataCount: byte;
  129. begin
  130. repeat
  131. if FBuffer.Empty then
  132. FThreadEvent.ResetEvent;
  133. FThreadEvent.WaitFor(INFINITE);
  134. DataCount := FBuffer.Peek(USBAspHidPacket[1], 8);
  135. SerialCountOrDataByte := DataCount;
  136. if (SerialCountOrDataByte = 8) and (USBAspHidPacket[8] = 7) then
  137. SerialCountOrDataByte := 7
  138. else
  139. if SerialCountOrDataByte < 8 then
  140. USBAspHidPacket[8] := SerialCountOrDataByte;
  141. if DataCount > 0 then
  142. begin
  143. SerialCountOrDataByte :=
  144. FHIDDevice^.Write(USBAspHidPacket, 8 + 1);
  145. FBuffer.AdvanceReadIdx(DataCount);
  146. end;
  147. until Terminated;
  148. end;
  149. end.