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