55 #include <sys/types.h> 58 #include <sys/ioctl.h> 70 #include "rnr/rnrconfig.h" 86 #define NOTBITS(bits) ~((uint_t)(bits)) 88 PRAGMA_IGNORED(sign-conversion)
98 PRAGMA_WARNING(sign-conversion)
104 #undef SERDEV_DEBUG // define for more debugging 113 #define SERDEVLOG(buffer, size, bNewLine) \ 114 {if(LOGABLE(LOG_LEVEL_DIAG4)) {SerDevLogBytes(buffer, size, bNewLine);}} 119 #define SERDEVLOGNL() \ 120 {if(LOGABLE(LOG_LEVEL_DIAG4)) {fprintf(LOG_GET_LOGFP(), "\n");}} 123 #define SERDEVLOG(buffer, size, bNewLine) 125 #define SERDEVLOGNL() 149 fp = LOG_GET_LOGFP();
151 for(n=0; n<size; ++n)
153 fprintf(fp,
"%s0x%02x", sep, buffer[n]);
176 if( gettimeofday(pTvMark, NULL) != OK )
178 LOGSYSERROR(
"gettimeofday()");
194 struct timeval tvEnd, tvDelta;
198 if( !timerisset(pTvMark) || !timerisset(&tvEnd) )
203 tvDelta.tv_sec = tvEnd.tv_sec - pTvMark->tv_sec;
204 if( tvEnd.tv_usec < pTvMark->tv_usec )
207 tvEnd.tv_usec += 1000000;
209 tvDelta.tv_usec = tvEnd.tv_usec - pTvMark->tv_usec;
211 return (uint_t)(tvDelta.tv_sec * 1000000 + tvDelta.tv_usec);
223 #define SERDEV_FIONREAD FIONREAD 225 #define SERDEV_FIONREAD 0x541b 228 #define SERDEV_NO_ATTR 0xffffffff 243 #define SERDEV_ATTR_ENTRY(attr) { (void *)#attr , attr } 249 #define SERDEV_GET_ATTR(attr) \ 250 SerDevAttrLookup(SerDevOptAttrTbl, \ 251 arraysize(SerDevOptAttrTbl), (void *)#attr, SerDevOptAttrCmp) 260 return strcmp((
const char *)pKey1, (
const char *)pKey2);
288 #ifdef CNEW_RTSCTS // try it with alternate constant name 298 #define SERDEV_BAUDRATE_ENTRY(baudrate) \ 299 { (void *)((unsigned long)baudrate), B##baudrate } 305 #define SERDEV_GET_BAUDRATE(baudrate) \ 306 SerDevAttrLookup(SerDevBaudRateTbl, arraysize(SerDevBaudRateTbl), \ 307 (void *)((unsigned long)baudrate), SerDevBaudRateCmp) 316 return (
unsigned long)pKey1 == (
unsigned long)pKey2? 0: 1;
434 const void *pKey,
int (*cmp)(
const void *,
const void *))
438 for(i=0; i<nTblEntries; ++i)
440 if( !cmp(tbl[i].m_pKey, pKey) )
472 speed_t ospeed, ispeed;
477 LOGERROR(
"Invalid serial device file descriptor: %d", fd);
483 if( tcgetattr(fd, &tios) == -1 )
485 LOGSYSERROR(
"tcgetattr(%d,...) failed", fd);
490 tios.c_cflag |= (CLOCAL|CREAD);
491 tios.c_lflag &=
NOTBITS(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG|IEXTEN);
502 tios.c_oflag &=
NOTBITS(OPOST);
504 tios.c_iflag &=
NOTBITS(INLCR|IGNCR|ICRNL|IGNBRK);
517 LOGERROR(
"Invalid/unsupported baud rate: %u", nBaudRate);
522 if( cfsetospeed(&tios, ospeed) == -1 )
524 LOGSYSERROR(
"tcsetospeed(tios,%u)", ospeed);
527 if( cfsetispeed(&tios, ispeed) == -1 )
529 LOGSYSERROR(
"tcsetispeed(tios,%u)", ispeed);
534 tios.c_cflag &=
NOTBITS(CSIZE);
550 LOGERROR(
"Invalid data byte size: %u", nByteSize);
559 tios.c_cflag &=
NOTBITS(CSTOPB);
562 tios.c_cflag |= (CSTOPB);
565 LOGERROR(
"Invalid number of stop bits: %u", nStopBits);
571 tios.c_iflag &=
NOTBITS(INPCK|ISTRIP);
575 tios.c_cflag &=
NOTBITS(PARENB|PARODD);
578 tios.c_cflag &=
NOTBITS(PARODD);
579 tios.c_cflag |= (PARENB);
582 tios.c_cflag |= (PARENB|PARODD);
585 LOGERROR(
"Invalid parity: %c", cParity);
595 tios.c_iflag |= (IXON|IXOFF);
599 tios.c_iflag &=
NOTBITS(IXON|IXOFF|IXANY);
606 tios.c_iflag |= (IXON|IXOFF);
610 tios.c_iflag &=
NOTBITS(IXON|IXOFF);
619 tios.c_cflag |= (CRTSCTS);
623 tios.c_cflag &=
NOTBITS(CRTSCTS);
631 tios.c_cflag |= (attr);
640 LOGDIAG4(
"Do not know how to set/clear RTS/CTS hardware flow control.");
646 tios.c_cc[VTIME] = 0;
649 if( tcsetattr(fd, TCSANOW, &tios) == -1 )
651 LOGSYSERROR(
"tcseattr(%d,TCSANOW,...)", fd);
673 LOGDIAG4CALL( _TSTR(sSerDevName),
681 fd = open(sSerDevName, O_RDWR|O_NONBLOCK|O_NOCTTY);
685 LOGSYSERROR(
"open(%s,...)", sSerDevName);
690 nStopBits, bRtsCts, bXonXoff) != OK )
692 LOGERROR(
"SerDevConfigure(): failed");
699 LOGDIAG4(
"Serial device %s opened", sSerDevName);
706 LOGDIAG4CALL(_TINT(fd));
710 LOGERROR(
"Invalid serial device file descriptor: %d", fd);
726 struct timeval tstart;
730 bool_t bInEol =
false;
736 if( (eol == NULL) || (*eol == 0) )
738 LOGERROR(
"No end-of-line sequence specified.");
748 while( len < count-1 )
782 LOGWARN(
"Unexpected character '%c' found in end-of-line sequence \"%s\".",
790 buffer[len++] = (char)c;
797 if( (usec > 0) && (tdelta >= usec) )
799 LOGDIAG4(
"%s() timed out", LOGFUNCNAME);
807 LOGERROR(
"Line > %zu characters long.", count);
817 size_t lenBuf, lenEol;
821 if( (eol == NULL) || (*eol == 0) )
823 LOGERROR(
"No end-of-line sequence specified.");
827 lenBuf = strlen(buffer);
828 lenEol = strlen(eol);
830 m =
SerDevWrite(fd, (byte_t *)buffer, lenBuf, usec);
833 if( (m == lenBuf) && (n == lenEol) )
847 struct timeval timeout;
851 LOGDIAG4CALL(_TINT(fd), _TUINT(usec));
860 timeout.tv_sec = (time_t)(usec / 1000000);
861 timeout.tv_usec = (time_t)(usec % 1000000);
863 nFd = select(fd+1, &rset, NULL, NULL, &timeout);
869 nFd = select(fd+1, &rset, NULL, NULL, NULL);
875 LOGSYSERROR(
"select(%d,...)", fd);
882 LOGDIAG4(
"select() on read timed out");
888 else if( (n = read(fd, &byte, (
size_t)1)) < 0 )
890 LOGSYSERROR(
"read(%d,...)", fd);
897 LOGERROR(
"0=read(%d,...)", fd);
905 LOGDIAG4(
"%s() byte=0x%02x read", LOGFUNCNAME, byte);
906 return (
int)(((uint_t)(byte)) & 0x00ff);
913 struct timeval timeout;
917 LOGDIAG4CALL(_TINT(fd), _THEX(byte), _TUINT(usec));
926 timeout.tv_sec = (time_t)(usec / 1000000);
927 timeout.tv_usec = (time_t)(usec % 1000000);
929 nFd = select(fd+1, NULL, &wset, NULL, &timeout);
935 nFd = select(fd+1, NULL, &wset, NULL, NULL);
941 LOGSYSERROR(
"select(%d,...)", fd);
948 LOGDIAG4(
"select() on write timed out");
954 else if( (n = write(fd, &byte, (
size_t)1)) < 0 )
956 LOGSYSERROR(
"write(%d,...)", fd);
963 LOGERROR(
"0=write(%d,...)", fd);
971 LOGDIAG4(
"%s() byte=0x%02x written", LOGFUNCNAME, byte);
972 return (
int)(((uint_t)(byte)) & 0x00ff);
976 ssize_t
SerDevRead(
int fd, byte_t *buffer,
size_t count, uint_t usec)
980 struct timeval tstart;
983 struct timeval timeout;
987 LOGDIAG4CALL(_TINT(fd), _TPTR(buffer), _TUINT(count), _TUINT(usec));
989 bNonBlocking = usec > 0?
true:
false;
991 while( nBytes < count )
1002 timeout.tv_sec = (time_t)(usec / 1000000);
1003 timeout.tv_usec = (time_t)(usec % 1000000);
1005 nFd = select(fd+1, &rset, NULL, NULL, &timeout);
1010 nFd = select(fd+1, &rset, NULL, NULL, NULL);
1016 LOGSYSERROR(
"select(%d,...)", fd);
1017 return (ssize_t)(RC_ERROR);
1023 LOGDIAG4(
"select() on read timed out");
1027 else if( (n = read(fd, buffer+nBytes, count-(
size_t)nBytes)) < 0 )
1029 LOGSYSERROR(
"read(%d,...)", fd);
1030 return (ssize_t)(RC_ERROR);
1040 if( (nBytes < count) && bNonBlocking )
1043 if( tdelta >= usec )
1045 LOGDIAG4(
"%s() timed out", LOGFUNCNAME);
1055 LOGDIAG4(
"%s() %lu bytes read", LOGFUNCNAME, nBytes);
1056 SERDEVLOG(buffer, (
size_t)nBytes,
true);
1061 ssize_t
SerDevWrite(
int fd, byte_t *buffer,
size_t count, uint_t usec)
1063 bool_t bNonBlocking;
1065 struct timeval tstart;
1068 struct timeval timeout;
1072 LOGDIAG4CALL(_TINT(fd), _TPTR(buffer), _TUINT(count), _TUINT(usec));
1074 bNonBlocking = usec > 0?
true:
false;
1076 while( nBytes < count )
1087 timeout.tv_sec = (time_t)(usec / 1000000);
1088 timeout.tv_usec = (time_t)(usec % 1000000);
1090 nFd = select(fd+1, NULL, &wset, NULL, &timeout);
1095 nFd = select(fd+1, NULL, &wset, NULL, NULL);
1101 LOGSYSERROR(
"select(%d,...)", fd);
1102 return (ssize_t)(RC_ERROR);
1108 LOGDIAG4(
"select() on write timed out");
1112 else if( (n = write(fd, buffer+nBytes, count-(
size_t)nBytes)) < 0 )
1114 LOGSYSERROR(
"write(%d,...)", fd);
1115 return (ssize_t)(RC_ERROR);
1125 if( (nBytes < count) && bNonBlocking )
1128 if( tdelta >= usec )
1130 LOGDIAG4(
"%s() timed out", LOGFUNCNAME);
1140 LOGDIAG4(
"%s() %lu bytes written", LOGFUNCNAME, nBytes);
1141 SERDEVLOG(buffer, (
size_t)nBytes,
true);
1148 unsigned int nBytes = 0;
1155 if( errno != ENOTTY )
1157 LOGSYSERROR(
"ioctl(%d,0x%x,...)", fd, SERDEV_FIONREAD);
1158 return (ssize_t)(RC_ERROR);
1167 return (ssize_t)nBytes;
1178 LOGDIAG4CALL(_TINT(fd));
1186 n = n < arraysize(b)? n: arraysize(b);
1206 LOGDIAG4CALL(_TINT(fd));
1210 tcflush(fd, TCIFLUSH);
1214 #endif // SERDEV_DEBUG 1218 LOGDIAG4CALL(_TINT(fd));
1220 tcflush(fd, TCOFLUSH);
1225 LOGDIAG4CALL(_TINT(fd));
1232 struct termios tios;
1233 speed_t ospeed, ispeed;
1235 LOGDIAG4CALL(_TINT(fd), _TINT(nBaudRate));
1238 if( tcgetattr(fd, &tios) == -1 )
1240 LOGSYSERROR(
"tcgetattr(%d,...) failed", fd);
1247 LOGERROR(
"Invalid/unsupported baud rate: %u", nBaudRate);
1252 if( cfsetospeed(&tios, ospeed) == -1 )
1254 LOGSYSERROR(
"tcsetospeed(tios,%u)", ospeed);
1257 if( cfsetispeed(&tios, ispeed) == -1 )
1259 LOGSYSERROR(
"tcsetispeed(tios,%u)", ispeed);
1268 struct termios tios;
1270 LOGDIAG4CALL(_TINT(fd), _TINT(nByteSize));
1273 tios.c_cflag &=
NOTBITS(CSIZE);
1277 tios.c_cflag |= CS8;
1280 tios.c_cflag |= CS7;
1283 tios.c_cflag |= CS6;
1286 tios.c_cflag |= CS5;
1289 LOGERROR(
"Invalid data byte size: %u", nByteSize);
1299 struct termios tios;
1301 LOGDIAG4CALL(_TINT(fd), _TCHAR(cParity));
1304 tios.c_iflag &=
NOTBITS(INPCK|ISTRIP);
1308 tios.c_cflag &=
NOTBITS(PARENB|PARODD);
1311 tios.c_cflag &=
NOTBITS(PARODD);
1312 tios.c_cflag |= (PARENB);
1315 tios.c_cflag |= (PARENB|PARODD);
1318 LOGERROR(
"Invalid parity: %c", cParity);
1328 struct termios tios;
1330 LOGDIAG4CALL(_TINT(fd), _TINT(nStopBits));
1336 tios.c_cflag &=
NOTBITS(CSTOPB);
1339 tios.c_cflag |= (CSTOPB);
1342 LOGERROR(
"Invalid number of stop bits: %u", nStopBits);
1352 struct termios tios;
1355 LOGDIAG4CALL(_TINT(fd), _TBOOL(bRtsCts));
1358 if( tcgetattr(fd, &tios) == -1 )
1360 LOGSYSERROR(
"tcgetattr(%d,...) failed", fd);
1369 tios.c_cflag |= (CRTSCTS);
1373 tios.c_cflag &=
NOTBITS(CRTSCTS);
1381 tios.c_cflag |= (attr);
1385 tios.c_cflag &=
NOTBITS(attr);
1390 LOGDIAG4(
"Do not know how to set/clear RTS/CTS hardware flow control.");
1395 if( tcflush(fd, TCIOFLUSH) == -1 )
1397 LOGSYSERROR(
"tcflush(%d,TCIOFLUSH)", fd);
1401 if( tcsetattr(fd, TCSANOW, &tios) == -1 )
1403 LOGSYSERROR(
"tcseattr(%d,TCSANOW,...)", fd);
1412 struct termios tios;
1415 LOGDIAG4CALL(_TINT(fd), _TBOOL(bXonXoff));
1418 if( tcgetattr(fd, &tios) == -1 )
1420 LOGSYSERROR(
"tcgetattr(%d,...) failed", fd);
1429 tios.c_iflag |= (IXON|IXOFF);
1433 tios.c_iflag &=
NOTBITS(IXON|IXOFF|IXANY);
1440 tios.c_iflag |= (IXON|IXOFF);
1444 tios.c_iflag &=
NOTBITS(IXON|IXOFF);
1449 if( tcsetattr(fd, TCSANOW, &tios) == -1 )
1451 LOGSYSERROR(
"tcseattr(%d,TCSANOW,...)", fd);
1462 if( ioctl(fd, TIOCMGET, &status) == -1 )
1464 LOGSYSERROR(
"ioctl(%d,TIOCMGET,...)", fd);
1468 status |= TIOCM_RTS;
1470 if( ioctl(fd, TIOCMSET, &status) == -1 )
1472 LOGSYSERROR(
"ioctl(%d,TIOCMSET,0x%x)", fd, status);
1483 if( ioctl(fd, TIOCMGET, &status) == -1 )
1485 LOGSYSERROR(
"ioctl(%d,TIOCMGET,...)", fd);
1489 status &= ~TIOCM_RTS;
1491 if( ioctl(fd, TIOCMSET, &status) == -1 )
1493 LOGSYSERROR(
"ioctl(%d,TIOCMSET,0x%x)", fd, status);
1504 if( ioctl(fd, TIOCMGET, &status) == -1 )
1506 LOGSYSERROR(
"ioctl(%d,TIOCMGET,...)", fd);
1510 status |= TIOCM_CTS;
1512 if( ioctl(fd, TIOCMSET, &status) == -1 )
1514 LOGSYSERROR(
"ioctl(%d,TIOCMSET,0x%x)", fd, status);
1525 if( ioctl(fd, TIOCMGET, &status) == -1 )
1527 LOGSYSERROR(
"ioctl(%d,TIOCMGET,...)", fd);
1531 status &= ~TIOCM_CTS;
1533 if( ioctl(fd, TIOCMSET, &status) == -1 )
1535 LOGSYSERROR(
"ioctl(%d,TIOCMSET,0x%x)", fd, status);
1546 int modem = TIOCM_RTS;
1549 if( ioctl(fd, TIOCMBIS, &modem) == -1 )
1551 LOGSYSERROR(
"ioctl(%d,TIOCMBIS,0x%x)", modem);
1560 int modem = TIOCM_RTS;
1563 if( ioctl(fd, TIOCMBIC, &modem) == -1 )
1565 LOGSYSERROR(
"ioctl(%d,TIOCMBIC,0x%x)", modem);
1574 int modem = TIOCM_CTS;
1577 if( ioctl(fd, TIOCMBIS, &modem) == -1 )
1579 LOGSYSERROR(
"ioctl(%d,TIOCMBIS,0x%x)", modem);
1588 int modem = TIOCM_CTS;
1591 if( ioctl(fd, TIOCMBIC, &modem) == -1 )
1593 LOGSYSERROR(
"ioctl(%d,TIOCMBIC,0x%x)", modem);
int SerDevSetParity(int fd, int cParity)
Set the parity.
#define SERDEV_BAUDRATE_ENTRY(baudrate)
Serial device supported baudrate macros.
#define SERDEV_GET_ATTR(attr)
Get I/O defined attribute value.
#define SERDEV_GET_BAUDRATE(baudrate)
Get baudrate defined value.
#define SERDEV_NO_ATTR
Special "No Attribute" value.
static SerDevAttrKvp_T SerDevOptAttrTbl[]
SerDevOptAttr table. Dynamic method to determine serial device optional defined attributes for each p...
ssize_t SerDevFIFOInputCount(int fd)
Determine the number of bytes in the input FIFO of the serial device.
int SerDevSetByteSize(int fd, int nByteSize)
Set the byte size.
ssize_t SerDevWrite(int fd, byte_t *buffer, size_t count, uint_t usec)
Write to serial device.
ssize_t SerDevWriteLine(int fd, char *buffer, char *eol, uint_t usec)
Write null-terminated ASCII character line to serial device.
unsigned int m_uVal
attribute value
int SerDevSetStopBits(int fd, int nStopBits)
Set the number of stop bits.
#define SERDEV_ATTR_ENTRY(attr)
Serial device attribute macros.
int SerDevSetSwFlowControl(int fd, bool_t bXonXoff)
Set software flow control state.
int SerDevAssertRTS(int fd)
Assert RTS (request to send).
int SerDevDeassertCTS(int fd)
De-assert RTS (clear to send).
int SerDevOpen(const char *sSerDevName, int nBaudRate, int nByteSize, int cParity, int nStopBits, bool_t bRtsCts, bool_t bXonXoff)
Open and configure serial device for communication.
void SerDevFIFOOutputDrain(int fd)
Transmit (drain) all data written to the output FIFO buffer.
RS-232 serial device communication declarations and defines.
ssize_t SerDevReadLine(int fd, char buffer[], size_t count, char *eol, uint_t usec)
Read a ASCII character line from the serial device.
static void SerDevLogBytes(byte_t buffer[], size_t size, bool_t bNewLine)
Log read/written bytes to log stream.
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
#define SERDEV_FIONREAD
number in input queue
static int SerDevOptAttrCmp(const void *pKey1, const void *pKey2)
Serial option attribute comparator.
ssize_t SerDevRead(int fd, byte_t *buffer, size_t count, uint_t usec)
Read from the serial device.
int SerDevSetBaudRate(int fd, int nBaudRate)
Set the baudrate.
#define SERDEVLOG(buffer, size, bNewLine)
Log read/written bytes to log stream.
static unsigned int SerDevAttrLookup(SerDevAttrKvp_T tbl[], size_t nTblEntries, const void *pKey, int(*cmp)(const void *, const void *))
Lookup the attribute value associated with the key.
void SerDevFIFOOutputFlush(int fd)
Flush output FIFO buffer, discarding all data in buffer.
static int SerDevBaudRateCmp(const void *pKey1, const void *pKey2)
BaudRate attribute comparator.
static int SerDevConfigure(int fd, int nBaudRate, int nByteSize, int cParity, int nStopBits, bool_t bRtsCts, bool_t bXonXoff)
(Re)configure a serial device attibutes.
Serial Device Attribute Key - Value Pair structure.
static SerDevAttrKvp_T SerDevBaudRateTbl[]
SerDevBaudRate table. Dynamic method to determine Serial device supported baud rates for each plaform...
int SerDevClose(int fd)
Close serial device port.
int SerDevDeassertRTS(int fd)
De-assert RTS (request to send).
#define SERDEVLOGNL()
Write newline character to log stream.
#define NOTBITS(bits)
Bitwise complement.
ssize_t SerDevFIFOInputFlush(int fd)
Flush the input FIFO buffer, discarding all data in buffer.
int SerDevSetHwFlowControl(int fd, bool_t bRtsCts)
Set hardware flow control state.
int SerDevPutc(int fd, byte_t byte, uint_t usec)
Put one character to serial device.
int SerDevAssertCTS(int fd)
Assert RTS (clear to send).
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
int SerDevGetc(int fd, uint_t usec)
Get 1 character from the serial device.
void * m_pKey
attribute key