serial.pp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. { Unit for handling the serial interfaces for Linux and similar Unices.
  2. (c) 2000 Sebastian Guenther, [email protected]; modified markMLl 2011.
  3. }
  4. unit Serial;
  5. {$MODE objfpc}
  6. {$H+}
  7. {$PACKRECORDS C}
  8. interface
  9. uses BaseUnix,termio,unix;
  10. type
  11. TSerialHandle = LongInt;
  12. TParityType = (NoneParity, OddParity, EvenParity);
  13. TSerialFlags = set of (RtsCtsFlowControl);
  14. TSerialState = record
  15. LineState: LongWord;
  16. tios: termios;
  17. end;
  18. { Open the serial device with the given device name, for example:
  19. /dev/ttyS0, /dev/ttyS1... for normal serial ports
  20. /dev/ttyI0, /dev/ttyI1... for ISDN emulated serial ports
  21. other device names are possible; refer to your OS documentation.
  22. Returns "0" if device could not be found }
  23. function SerOpen(const DeviceName: String): TSerialHandle;
  24. { Closes a serial device previously opened with SerOpen. }
  25. procedure SerClose(Handle: TSerialHandle);
  26. { Flushes the data queues of the given serial device. DO NOT USE THIS:
  27. use either SerSync (non-blocking) or SerDrain (blocking). }
  28. procedure SerFlush(Handle: TSerialHandle); deprecated;
  29. { Suggest to the kernel that buffered output data should be sent. This
  30. is unlikely to have a useful effect except possibly in the case of
  31. buggy ports that lose Tx interrupts, and is implemented as a preferred
  32. alternative to the deprecated SerFlush procedure. }
  33. procedure SerSync(Handle: TSerialHandle);
  34. { Wait until all buffered output has been transmitted. It is the caller's
  35. responsibility to ensure that this won't block permanently due to an
  36. inappropriate handshake state. }
  37. procedure SerDrain(Handle: TSerialHandle);
  38. { Discard all pending input. }
  39. procedure SerFlushInput(Handle: TSerialHandle);
  40. { Discard all unsent output. }
  41. procedure SerFlushOutput(Handle: TSerialHandle);
  42. { Reads a maximum of "Count" bytes of data into the specified buffer.
  43. Result: Number of bytes read. }
  44. function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;
  45. { Tries to write "Count" bytes from "Buffer".
  46. Result: Number of bytes written. }
  47. function SerWrite(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;
  48. procedure SerSetParams(Handle: TSerialHandle; BitsPerSec: LongInt;
  49. ByteSize: Integer; Parity: TParityType; StopBits: Integer;
  50. Flags: TSerialFlags);
  51. { Saves and restores the state of the serial device. }
  52. function SerSaveState(Handle: TSerialHandle): TSerialState;
  53. procedure SerRestoreState(Handle: TSerialHandle; State: TSerialState);
  54. { Getting and setting the line states directly. }
  55. procedure SerSetDTR(Handle: TSerialHandle; State: Boolean);
  56. procedure SerSetRTS(Handle: TSerialHandle; State: Boolean);
  57. function SerGetCTS(Handle: TSerialHandle): Boolean;
  58. function SerGetDSR(Handle: TSerialHandle): Boolean;
  59. function SerGetCD(Handle: TSerialHandle): Boolean;
  60. function SerGetRI(Handle: TSerialHandle): Boolean;
  61. { ************************************************************************** }
  62. implementation
  63. function SerOpen(const DeviceName: String): TSerialHandle;
  64. begin
  65. Result := fpopen(DeviceName, O_RDWR or O_NOCTTY);
  66. end;
  67. procedure SerClose(Handle: TSerialHandle);
  68. begin
  69. fpClose(Handle);
  70. end;
  71. procedure SerFlush(Handle: TSerialHandle); deprecated;
  72. begin
  73. fpfsync(Handle);
  74. end;
  75. procedure SerSync(Handle: TSerialHandle);
  76. begin
  77. fpfsync(Handle)
  78. end;
  79. procedure SerDrain(Handle: TSerialHandle);
  80. begin
  81. tcdrain(Handle)
  82. end;
  83. procedure SerFlushInput(Handle: TSerialHandle);
  84. begin
  85. tcflush(Handle, TCIFLUSH)
  86. end;
  87. procedure SerFlushOutput(Handle: TSerialHandle);
  88. begin
  89. tcflush(Handle, TCOFLUSH)
  90. end;
  91. function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;
  92. begin
  93. Result := fpRead(Handle, Buffer, Count);
  94. end;
  95. function SerWrite(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt;
  96. begin
  97. Result := fpWrite(Handle, Buffer, Count);
  98. end;
  99. procedure SerSetParams(Handle: TSerialHandle; BitsPerSec: LongInt;
  100. ByteSize: Integer; Parity: TParityType; StopBits: Integer;
  101. Flags: TSerialFlags);
  102. var
  103. tios: termios;
  104. begin
  105. FillChar(tios, SizeOf(tios), #0);
  106. case BitsPerSec of
  107. 50: tios.c_cflag := B50;
  108. 75: tios.c_cflag := B75;
  109. 110: tios.c_cflag := B110;
  110. 134: tios.c_cflag := B134;
  111. 150: tios.c_cflag := B150;
  112. 200: tios.c_cflag := B200;
  113. 300: tios.c_cflag := B300;
  114. 600: tios.c_cflag := B600;
  115. 1200: tios.c_cflag := B1200;
  116. 1800: tios.c_cflag := B1800;
  117. 2400: tios.c_cflag := B2400;
  118. 4800: tios.c_cflag := B4800;
  119. 19200: tios.c_cflag := B19200;
  120. 38400: tios.c_cflag := B38400;
  121. 57600: tios.c_cflag := B57600;
  122. 115200: tios.c_cflag := B115200;
  123. 230400: tios.c_cflag := B230400;
  124. {$ifndef BSD}
  125. 460800: tios.c_cflag := B460800;
  126. {$endif}
  127. else tios.c_cflag := B9600;
  128. end;
  129. tios.c_ispeed := tios.c_cflag;
  130. tios.c_ospeed := tios.c_ispeed;
  131. tios.c_cflag := tios.c_cflag or CREAD or CLOCAL;
  132. case ByteSize of
  133. 5: tios.c_cflag := tios.c_cflag or CS5;
  134. 6: tios.c_cflag := tios.c_cflag or CS6;
  135. 7: tios.c_cflag := tios.c_cflag or CS7;
  136. else tios.c_cflag := tios.c_cflag or CS8;
  137. end;
  138. case Parity of
  139. OddParity: tios.c_cflag := tios.c_cflag or PARENB or PARODD;
  140. EvenParity: tios.c_cflag := tios.c_cflag or PARENB;
  141. end;
  142. if StopBits = 2 then
  143. tios.c_cflag := tios.c_cflag or CSTOPB;
  144. if RtsCtsFlowControl in Flags then
  145. tios.c_cflag := tios.c_cflag or CRTSCTS;
  146. tcflush(Handle, TCIOFLUSH);
  147. tcsetattr(Handle, TCSANOW, tios)
  148. end;
  149. function SerSaveState(Handle: TSerialHandle): TSerialState;
  150. begin
  151. fpioctl(Handle, TIOCMGET, @Result.LineState);
  152. // fpioctl(Handle, TCGETS, @Result.tios);
  153. TcGetAttr(handle,result.tios);
  154. end;
  155. procedure SerRestoreState(Handle: TSerialHandle; State: TSerialState);
  156. begin
  157. // fpioctl(Handle, TCSETS, @State.tios);
  158. TCSetAttr(handle,TCSANOW,State.tios);
  159. fpioctl(Handle, TIOCMSET, @State.LineState);
  160. end;
  161. procedure SerSetDTR(Handle: TSerialHandle; State: Boolean);
  162. const
  163. DTR: Cardinal = TIOCM_DTR;
  164. begin
  165. if State then
  166. fpioctl(Handle, TIOCMBIS, @DTR)
  167. else
  168. fpioctl(Handle, TIOCMBIC, @DTR);
  169. end;
  170. procedure SerSetRTS(Handle: TSerialHandle; State: Boolean);
  171. const
  172. RTS: Cardinal = TIOCM_RTS;
  173. begin
  174. if State then
  175. fpioctl(Handle, TIOCMBIS, @RTS)
  176. else
  177. fpioctl(Handle, TIOCMBIC, @RTS);
  178. end;
  179. function SerGetCTS(Handle: TSerialHandle): Boolean;
  180. var
  181. Flags: Cardinal;
  182. begin
  183. fpioctl(Handle, TIOCMGET, @Flags);
  184. Result := (Flags and TIOCM_CTS) <> 0;
  185. end;
  186. function SerGetDSR(Handle: TSerialHandle): Boolean;
  187. var
  188. Flags: Cardinal;
  189. begin
  190. fpioctl(Handle, TIOCMGET, @Flags);
  191. Result := (Flags and TIOCM_DSR) <> 0;
  192. end;
  193. function SerGetCD(Handle: TSerialHandle): Boolean;
  194. var
  195. Flags: Cardinal;
  196. begin
  197. fpioctl(Handle, TIOCMGET, @Flags);
  198. Result := (Flags and TIOCM_CD) <> 0
  199. end;
  200. function SerGetRI(Handle: TSerialHandle): Boolean;
  201. var
  202. Flags: Cardinal;
  203. begin
  204. fpioctl(Handle, TIOCMGET, @Flags);
  205. Result := (Flags and TIOCM_RI) <> 0;
  206. end;
  207. end.