{ Unit for handling the serial interfaces for Linux and similar Unices. (c) 2000 Sebastian Guenther, sg@freepascal.org } unit Serial; {$MODE objfpc} {$H+} {$PACKRECORDS C} interface uses BaseUnix,termio,unix; type TSerialHandle = LongInt; TParityType = (NoneParity, OddParity, EvenParity); TSerialFlags = set of (RtsCtsFlowControl); TSerialState = record LineState: LongWord; tios: termios; end; { Open the serial device with the given device name, for example: /dev/ttyS0, /dev/ttyS1... for normal serial ports /dev/ttyI0, /dev/ttyI1... for ISDN emulated serial ports other device names are possible; refer to your OS documentation. Returns "0" if device could not be found } function SerOpen(const DeviceName: String): TSerialHandle; { Closes a serial device previously opened with SerOpen. } procedure SerClose(Handle: TSerialHandle); { Flushes the data queues of the given serial device. } procedure SerFlush(Handle: TSerialHandle); { Reads a maximum of "Count" bytes of data into the specified buffer. Result: Number of bytes read. } function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt; { Tries to write "Count" bytes from "Buffer". Result: Number of bytes written. } function SerWrite(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt; procedure SerSetParams(Handle: TSerialHandle; BitsPerSec: LongInt; ByteSize: Integer; Parity: TParityType; StopBits: Integer; Flags: TSerialFlags); { Saves and restores the state of the serial device. } function SerSaveState(Handle: TSerialHandle): TSerialState; procedure SerRestoreState(Handle: TSerialHandle; State: TSerialState); { Getting and setting the line states directly. } procedure SerSetDTR(Handle: TSerialHandle; State: Boolean); procedure SerSetRTS(Handle: TSerialHandle; State: Boolean); function SerGetCTS(Handle: TSerialHandle): Boolean; function SerGetDSR(Handle: TSerialHandle): Boolean; function SerGetRI(Handle: TSerialHandle): Boolean; { ************************************************************************** } implementation function SerOpen(const DeviceName: String): TSerialHandle; begin Result := fpopen(DeviceName, O_RDWR or O_NOCTTY); end; procedure SerClose(Handle: TSerialHandle); begin fpClose(Handle); end; procedure SerFlush(Handle: TSerialHandle); begin fsync(Handle); end; function SerRead(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt; begin Result := fpRead(Handle, Buffer, Count); end; function SerWrite(Handle: TSerialHandle; var Buffer; Count: LongInt): LongInt; begin Result := fpWrite(Handle, Buffer, Count); end; procedure SerSetParams(Handle: TSerialHandle; BitsPerSec: LongInt; ByteSize: Integer; Parity: TParityType; StopBits: Integer; Flags: TSerialFlags); var tios: termios; begin FillChar(tios, SizeOf(tios), #0); case BitsPerSec of 50: tios.c_cflag := B50; 75: tios.c_cflag := B75; 110: tios.c_cflag := B110; 134: tios.c_cflag := B134; 150: tios.c_cflag := B150; 200: tios.c_cflag := B200; 300: tios.c_cflag := B300; 600: tios.c_cflag := B600; 1200: tios.c_cflag := B1200; 1800: tios.c_cflag := B1800; 2400: tios.c_cflag := B2400; 4800: tios.c_cflag := B4800; 19200: tios.c_cflag := B19200; 38400: tios.c_cflag := B38400; 57600: tios.c_cflag := B57600; 115200: tios.c_cflag := B115200; 230400: tios.c_cflag := B230400; {$ifndef BSD} 460800: tios.c_cflag := B460800; {$endif} else tios.c_cflag := B9600; end; tios.c_ispeed := tios.c_cflag; tios.c_ospeed := tios.c_ispeed; tios.c_cflag := tios.c_cflag or CREAD or CLOCAL; case ByteSize of 5: tios.c_cflag := tios.c_cflag or CS5; 6: tios.c_cflag := tios.c_cflag or CS6; 7: tios.c_cflag := tios.c_cflag or CS7; else tios.c_cflag := tios.c_cflag or CS8; end; case Parity of OddParity: tios.c_cflag := tios.c_cflag or PARENB or PARODD; EvenParity: tios.c_cflag := tios.c_cflag or PARENB; end; if StopBits = 2 then tios.c_cflag := tios.c_cflag or CSTOPB; if RtsCtsFlowControl in Flags then tios.c_cflag := tios.c_cflag or CRTSCTS; tcflush(Handle, TCIOFLUSH); tcsetattr(Handle, TCSANOW, tios) end; function SerSaveState(Handle: TSerialHandle): TSerialState; begin fpioctl(Handle, TIOCMGET, @Result.LineState); // fpioctl(Handle, TCGETS, @Result.tios); TcGetAttr(handle,result.tios); end; procedure SerRestoreState(Handle: TSerialHandle; State: TSerialState); begin // fpioctl(Handle, TCSETS, @State.tios); TCSetAttr(handle,TCSANOW,State.tios); fpioctl(Handle, TIOCMSET, @State.LineState); end; procedure SerSetDTR(Handle: TSerialHandle; State: Boolean); const DTR: Cardinal = TIOCM_DTR; begin if State then fpioctl(Handle, TIOCMBIS, @DTR) else fpioctl(Handle, TIOCMBIC, @DTR); end; procedure SerSetRTS(Handle: TSerialHandle; State: Boolean); const RTS: Cardinal = TIOCM_RTS; begin if State then fpioctl(Handle, TIOCMBIS, @RTS) else fpioctl(Handle, TIOCMBIC, @RTS); end; function SerGetCTS(Handle: TSerialHandle): Boolean; var Flags: Cardinal; begin fpioctl(Handle, TIOCMGET, @Flags); Result := (Flags and TIOCM_CTS) <> 0; end; function SerGetDSR(Handle: TSerialHandle): Boolean; var Flags: Cardinal; begin fpioctl(Handle, TIOCMGET, @Flags); Result := (Flags and TIOCM_DSR) <> 0; end; function SerGetRI(Handle: TSerialHandle): Boolean; var Flags: Cardinal; begin fpioctl(Handle, TIOCMGET, @Flags); Result := (Flags and TIOCM_RI) <> 0; end; end. { $Log$ Revision 1.10 2003-11-19 17:11:40 marco * termio unit Revision 1.9 2003/11/19 10:54:32 marco * some simple restructures Revision 1.8 2003/09/14 20:15:01 marco * Unix reform stage two. Remove all calls from Unix that exist in Baseunix. Revision 1.7 2002/09/07 16:01:27 peter * old logs removed and tabs fixed Revision 1.6 2002/08/06 13:31:50 sg * serial ports are now set to raw mode }