libserial  1.6.2
RoadNarrows Roboitics Serial Library
serdev.c File Reference

RS-232 serial device communication definitions. More...

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <limits.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include "rnr/rnrconfig.h"
#include "rnr/log.h"
#include "rnr/new.h"
#include "rnr/serdev.h"

Go to the source code of this file.

Classes

struct  SerDevAttrKvp_T
 Serial Device Attribute Key - Value Pair structure. More...
 

Macros

#define NOTBITS(bits)   ~((uint_t)(bits))
 Bitwise complement. More...
 
#define SERDEVLOG(buffer, size, bNewLine)   {if(LOGABLE(LOG_LEVEL_DIAG4)) {SerDevLogBytes(buffer, size, bNewLine);}}
 Log read/written bytes to log stream. More...
 
#define SERDEVLOGNL()   {if(LOGABLE(LOG_LEVEL_DIAG4)) {fprintf(LOG_GET_LOGFP(), "\n");}}
 Write newline character to log stream.
 
#define SERDEV_FIONREAD   0x541b
 number in input queue
 
#define SERDEV_NO_ATTR   0xffffffff
 Special "No Attribute" value.
 
#define SERDEV_ATTR_ENTRY(attr)   { (void *)#attr , attr }
 Serial device attribute macros. More...
 
#define SERDEV_GET_ATTR(attr)
 Get I/O defined attribute value. More...
 
#define SERDEV_BAUDRATE_ENTRY(baudrate)   { (void *)((unsigned long)baudrate), B##baudrate }
 Serial device supported baudrate macros. More...
 
#define SERDEV_GET_BAUDRATE(baudrate)
 Get baudrate defined value. More...
 

Functions

static void fdset_nowarn (int fd, fd_set *pset)
 FD_SET() wrapper with no annoying warnings. More...
 
static void SerDevLogBytes (byte_t buffer[], size_t size, bool_t bNewLine)
 Log read/written bytes to log stream. More...
 
static void timer_mark (struct timeval *pTvMark)
 Mark the current time. Resolution is microseconds. More...
 
static uint_t timer_elapsed (struct timeval *pTvMark)
 Calculate the elapsed time between the given time mark and this call. More...
 
static int SerDevOptAttrCmp (const void *pKey1, const void *pKey2)
 Serial option attribute comparator. More...
 
static int SerDevBaudRateCmp (const void *pKey1, const void *pKey2)
 BaudRate attribute comparator. More...
 
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. More...
 
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. More...
 
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. More...
 
int SerDevClose (int fd)
 Close serial device port. More...
 
ssize_t SerDevReadLine (int fd, char buffer[], size_t count, char *eol, uint_t usec)
 Read a ASCII character line from the serial device. More...
 
ssize_t SerDevWriteLine (int fd, char *buffer, char *eol, uint_t usec)
 Write null-terminated ASCII character line to serial device. More...
 
int SerDevGetc (int fd, uint_t usec)
 Get 1 character from the serial device. More...
 
int SerDevPutc (int fd, byte_t byte, uint_t usec)
 Put one character to serial device. More...
 
ssize_t SerDevRead (int fd, byte_t *buffer, size_t count, uint_t usec)
 Read from the serial device. More...
 
ssize_t SerDevWrite (int fd, byte_t *buffer, size_t count, uint_t usec)
 Write to serial device. More...
 
ssize_t SerDevFIFOInputCount (int fd)
 Determine the number of bytes in the input FIFO of the serial device. More...
 
ssize_t SerDevFIFOInputFlush (int fd)
 Flush the input FIFO buffer, discarding all data in buffer. More...
 
void SerDevFIFOOutputFlush (int fd)
 Flush output FIFO buffer, discarding all data in buffer. More...
 
void SerDevFIFOOutputDrain (int fd)
 Transmit (drain) all data written to the output FIFO buffer. More...
 
int SerDevSetBaudRate (int fd, int nBaudRate)
 Set the baudrate. More...
 
int SerDevSetByteSize (int fd, int nByteSize)
 Set the byte size. More...
 
int SerDevSetParity (int fd, int cParity)
 Set the parity. More...
 
int SerDevSetStopBits (int fd, int nStopBits)
 Set the number of stop bits. More...
 
int SerDevSetHwFlowControl (int fd, bool_t bRtsCts)
 Set hardware flow control state. More...
 
int SerDevSetSwFlowControl (int fd, bool_t bXonXoff)
 Set software flow control state. More...
 
int SerDevAssertRTS (int fd)
 Assert RTS (request to send). More...
 
int SerDevDeassertRTS (int fd)
 De-assert RTS (request to send). More...
 
int SerDevAssertCTS (int fd)
 Assert RTS (clear to send). More...
 
int SerDevDeassertCTS (int fd)
 De-assert RTS (clear to send). More...
 

Variables

static SerDevAttrKvp_T SerDevOptAttrTbl []
 SerDevOptAttr table. Dynamic method to determine serial device optional defined attributes for each plaform architecture. More...
 
static SerDevAttrKvp_T SerDevBaudRateTbl []
 SerDevBaudRate table. Dynamic method to determine Serial device supported baud rates for each plaform architecture.
 

Detailed Description

RS-232 serial device communication definitions.

LastChangedDate
2015-02-24 12:58:53 -0700 (Tue, 24 Feb 2015)
Rev
3870

Ported from ipserddev.c (RoadNarrows)

Author
Robin Knight (robin.nosp@m..kni.nosp@m.ght@r.nosp@m.oadn.nosp@m.arrow.nosp@m.s.co.nosp@m.m)

Definition in file serdev.c.

Macro Definition Documentation

#define NOTBITS (   bits)    ~((uint_t)(bits))

Bitwise complement.

Parameters
bitsBits.

Definition at line 86 of file serdev.c.

Referenced by SerDevConfigure(), SerDevSetByteSize(), SerDevSetHwFlowControl(), SerDevSetParity(), SerDevSetStopBits(), and SerDevSetSwFlowControl().

#define SERDEV_ATTR_ENTRY (   attr)    { (void *)#attr , attr }

Serial device attribute macros.

Parameters
attrAttribute define.

Definition at line 243 of file serdev.c.

#define SERDEV_BAUDRATE_ENTRY (   baudrate)    { (void *)((unsigned long)baudrate), B##baudrate }

Serial device supported baudrate macros.

Parameters
baudrateInteger baudrate.

Definition at line 298 of file serdev.c.

#define SERDEV_GET_ATTR (   attr)
Value:
arraysize(SerDevOptAttrTbl), (void *)#attr, SerDevOptAttrCmp)
static SerDevAttrKvp_T SerDevOptAttrTbl[]
SerDevOptAttr table. Dynamic method to determine serial device optional defined attributes for each p...
Definition: serdev.c:268
static int SerDevOptAttrCmp(const void *pKey1, const void *pKey2)
Serial option attribute comparator.
Definition: serdev.c:258
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.
Definition: serdev.c:433

Get I/O defined attribute value.

Parameters
attrAttribute define.

Definition at line 249 of file serdev.c.

Referenced by SerDevConfigure(), SerDevSetHwFlowControl(), and SerDevSetSwFlowControl().

#define SERDEV_GET_BAUDRATE (   baudrate)
Value:
(void *)((unsigned long)baudrate), SerDevBaudRateCmp)
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.
Definition: serdev.c:433
static int SerDevBaudRateCmp(const void *pKey1, const void *pKey2)
BaudRate attribute comparator.
Definition: serdev.c:314
static SerDevAttrKvp_T SerDevBaudRateTbl[]
SerDevBaudRate table. Dynamic method to determine Serial device supported baud rates for each plaform...
Definition: serdev.c:324

Get baudrate defined value.

Parameters
baudrateInteger baudrate.

Definition at line 305 of file serdev.c.

Referenced by SerDevConfigure(), and SerDevSetBaudRate().

#define SERDEVLOG (   buffer,
  size,
  bNewLine 
)    {if(LOGABLE(LOG_LEVEL_DIAG4)) {SerDevLogBytes(buffer, size, bNewLine);}}

Log read/written bytes to log stream.

Parameters
bufferBuffer of bytes.
sizeNumber of bytes in buffer to log.
bNewLineDo [not] output trailing newline.

Definition at line 113 of file serdev.c.

Referenced by SerDevFIFOInputCount(), SerDevRead(), and SerDevWrite().

Function Documentation

static void fdset_nowarn ( int  fd,
fd_set *  pset 
)
inlinestatic

FD_SET() wrapper with no annoying warnings.

Parameters
fdFile descriptor to add to set.
psetPointer to fd set.

Definition at line 94 of file serdev.c.

Referenced by SerDevGetc(), SerDevPutc(), SerDevRead(), and SerDevWrite().

95 {
96  FD_SET(fd, pset);
97 }
int SerDevAssertCTS ( int  fd)

Assert RTS (clear to send).

Parameters
fdFile descriptor to the opened serial device.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1500 of file serdev.c.

Referenced by SerDevDeassertCTS(), and SerDevIsInputDataPresent().

1501 {
1502  int status;
1503 
1504  if( ioctl(fd, TIOCMGET, &status) == -1 )
1505  {
1506  LOGSYSERROR("ioctl(%d,TIOCMGET,...)", fd);
1507  return RC_ERROR;
1508  }
1509 
1510  status |= TIOCM_CTS;
1511 
1512  if( ioctl(fd, TIOCMSET, &status) == -1 )
1513  {
1514  LOGSYSERROR("ioctl(%d,TIOCMSET,0x%x)", fd, status);
1515  return RC_ERROR;
1516  }
1517 
1518  return OK;
1519 }
int SerDevAssertRTS ( int  fd)

Assert RTS (request to send).

Parameters
fdFile descriptor to the opened serial device.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1458 of file serdev.c.

Referenced by SerDevDeassertCTS(), and SerDevIsInputDataPresent().

1459 {
1460  int status;
1461 
1462  if( ioctl(fd, TIOCMGET, &status) == -1 )
1463  {
1464  LOGSYSERROR("ioctl(%d,TIOCMGET,...)", fd);
1465  return RC_ERROR;
1466  }
1467 
1468  status |= TIOCM_RTS;
1469 
1470  if( ioctl(fd, TIOCMSET, &status) == -1 )
1471  {
1472  LOGSYSERROR("ioctl(%d,TIOCMSET,0x%x)", fd, status);
1473  return RC_ERROR;
1474  }
1475 
1476  return OK;
1477 }
static unsigned int SerDevAttrLookup ( SerDevAttrKvp_T  tbl[],
size_t  nTblEntries,
const void *  pKey,
int(*)(const void *, const void *)  cmp 
)
static

Lookup the attribute value associated with the key.

Parameters
tbl[]Attribute Key-Value Pair table.
nTblEntriesNumber of Key-Value Pair table entries.
pKeyKey to lookup.
cmpAttribute key comparator function.
Returns
The associated attribute value on success, or SERDEV_NO_ATTR if the search failed.

Definition at line 433 of file serdev.c.

References SerDevAttrKvp_T::m_uVal, and SERDEV_NO_ATTR.

435 {
436  int i;
437 
438  for(i=0; i<nTblEntries; ++i)
439  {
440  if( !cmp(tbl[i].m_pKey, pKey) )
441  {
442  return tbl[i].m_uVal;
443  }
444  }
445  return SERDEV_NO_ATTR;
446 }
#define SERDEV_NO_ATTR
Special "No Attribute" value.
Definition: serdev.c:228
unsigned int m_uVal
attribute value
Definition: serdev.c:236
static int SerDevBaudRateCmp ( const void *  pKey1,
const void *  pKey2 
)
inlinestatic

BaudRate attribute comparator.

Parameters
pKey1Attribute key 1
pKey2Attribute key 2

Definition at line 314 of file serdev.c.

315 {
316  return (unsigned long)pKey1 == (unsigned long)pKey2? 0: 1;
317 }
int SerDevClose ( int  fd)

Close serial device port.

Parameters
fdFile descriptor to the opened serial device.
Returns
On success, OK(0) is returned.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 704 of file serdev.c.

705 {
706  LOGDIAG4CALL(_TINT(fd));
707 
708  if( fd < 0 )
709  {
710  LOGERROR("Invalid serial device file descriptor: %d", fd);
711  errno = EBADF;
712  return RC_ERROR;
713  }
714  else
715  {
716  return close(fd);
717  }
718 }
static int SerDevConfigure ( int  fd,
int  nBaudRate,
int  nByteSize,
int  cParity,
int  nStopBits,
bool_t  bRtsCts,
bool_t  bXonXoff 
)
static

(Re)configure a serial device attibutes.

Parameters
fdFile descriptor to the opened serial device.
nBaudRateBaud rate.
nByteSizeBytes size in bits 5...8.
cParityParity. One of: 'N', 'E', 'O'
nStopBitsNumber of stop bits 1, 2
bRtsCtsDo [not] use hardware flow control.
bXonXoffDo [not] use software flow control.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 463 of file serdev.c.

References NOTBITS, SERDEV_GET_ATTR, SERDEV_GET_BAUDRATE, and SERDEV_NO_ATTR.

Referenced by SerDevOpen().

470 {
471  struct termios tios;
472  speed_t ospeed, ispeed;
473  uint_t attr;
474 
475  if( fd < 0 )
476  {
477  LOGERROR("Invalid serial device file descriptor: %d", fd);
478  errno = EBADF;
479  return RC_ERROR;
480  }
481 
482  // get the current device attributes
483  if( tcgetattr(fd, &tios) == -1 )
484  {
485  LOGSYSERROR("tcgetattr(%d,...) failed", fd);
486  return RC_ERROR;
487  }
488 
489  // set up raw mode / no echo / binary
490  tios.c_cflag |= (CLOCAL|CREAD);
491  tios.c_lflag &= NOTBITS(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG|IEXTEN);
492  // |ECHOPRT
493  if( (attr = SERDEV_GET_ATTR(ECHOCTL)) != SERDEV_NO_ATTR )
494  {
495  tios.c_lflag &= NOTBITS(attr);
496  }
497  if( (attr = SERDEV_GET_ATTR(ECHOKE)) != SERDEV_NO_ATTR )
498  {
499  tios.c_lflag &= NOTBITS(attr);
500  }
501 
502  tios.c_oflag &= NOTBITS(OPOST);
503 
504  tios.c_iflag &= NOTBITS(INLCR|IGNCR|ICRNL|IGNBRK);
505  if( (attr = SERDEV_GET_ATTR(IOCLC)) != SERDEV_NO_ATTR )
506  {
507  tios.c_iflag &= NOTBITS(attr);
508  }
509  if( (attr = SERDEV_GET_ATTR(PARMRK)) != SERDEV_NO_ATTR )
510  {
511  tios.c_iflag &= NOTBITS(attr);
512  }
513 
514  // set up baudrate
515  if((ospeed = SERDEV_GET_BAUDRATE(nBaudRate)) == SERDEV_NO_ATTR)
516  {
517  LOGERROR("Invalid/unsupported baud rate: %u", nBaudRate);
518  errno = EINVAL;
519  return RC_ERROR;
520  }
521  ispeed = ospeed;
522  if( cfsetospeed(&tios, ospeed) == -1 ) // set output baudrate in structure
523  {
524  LOGSYSERROR("tcsetospeed(tios,%u)", ospeed);
525  return RC_ERROR;
526  }
527  if( cfsetispeed(&tios, ispeed) == -1 ) // set input baudrate in structure
528  {
529  LOGSYSERROR("tcsetispeed(tios,%u)", ispeed);
530  return RC_ERROR;
531  }
532 
533  // set up data character size (bits)
534  tios.c_cflag &= NOTBITS(CSIZE);
535  switch( nByteSize )
536  {
537  case 8:
538  tios.c_cflag |= CS8;
539  break;
540  case 7:
541  tios.c_cflag |= CS7;
542  break;
543  case 6:
544  tios.c_cflag |= CS6;
545  break;
546  case 5:
547  tios.c_cflag |= CS5;
548  break;
549  default:
550  LOGERROR("Invalid data byte size: %u", nByteSize);
551  errno = EINVAL;
552  return RC_ERROR;
553  }
554 
555  // set up stopbits
556  switch( nStopBits )
557  {
558  case 1:
559  tios.c_cflag &= NOTBITS(CSTOPB);
560  break;
561  case 2:
562  tios.c_cflag |= (CSTOPB);
563  break;
564  default:
565  LOGERROR("Invalid number of stop bits: %u", nStopBits);
566  errno = EINVAL;
567  return RC_ERROR;
568  }
569 
570  // set up parity
571  tios.c_iflag &= NOTBITS(INPCK|ISTRIP);
572  switch( cParity )
573  {
574  case 'N':
575  tios.c_cflag &= NOTBITS(PARENB|PARODD);
576  break;
577  case 'E':
578  tios.c_cflag &= NOTBITS(PARODD);
579  tios.c_cflag |= (PARENB);
580  break;
581  case 'O':
582  tios.c_cflag |= (PARENB|PARODD);
583  break;
584  default:
585  LOGERROR("Invalid parity: %c", cParity);
586  errno = EINVAL;
587  return RC_ERROR;
588  }
589 
590  // set up xon/xoff software flow control
591  if( (attr = SERDEV_GET_ATTR(IXANY)) != SERDEV_NO_ATTR )
592  {
593  if( bXonXoff )
594  {
595  tios.c_iflag |= (IXON|IXOFF); // |IXANY)
596  }
597  else
598  {
599  tios.c_iflag &= NOTBITS(IXON|IXOFF|IXANY);
600  }
601  }
602  else
603  {
604  if( bXonXoff )
605  {
606  tios.c_iflag |= (IXON|IXOFF);
607  }
608  else
609  {
610  tios.c_iflag &= NOTBITS(IXON|IXOFF);
611  }
612  }
613 
614  // set up rts/cts hardware flow control
615  if( (attr = SERDEV_GET_ATTR(CRTSCTS)) != SERDEV_NO_ATTR )
616  {
617  if( bRtsCts )
618  {
619  tios.c_cflag |= (CRTSCTS);
620  }
621  else
622  {
623  tios.c_cflag &= NOTBITS(CRTSCTS);
624  }
625  }
626  // try it with alternate constant name
627  else if( (attr = SERDEV_GET_ATTR(CNEW_RTSCTS)) != SERDEV_NO_ATTR )
628  {
629  if( bRtsCts )
630  {
631  tios.c_cflag |= (attr);
632  }
633  else
634  {
635  tios.c_cflag &= NOTBITS(attr);
636  }
637  }
638  else
639  {
640  LOGDIAG4("Do not know how to set/clear RTS/CTS hardware flow control.");
641  }
642 
643  // set up read buffering for non-blocking (vmin, vtime are byte values)
644  // select() will handle timeouts.
645  tios.c_cc[VMIN] = 0; // vmin is minimum number of characters to be read.
646  tios.c_cc[VTIME] = 0; // vtime is read timout in deciseconds
647 
648  // activate the serial device settings
649  if( tcsetattr(fd, TCSANOW, &tios) == -1 )
650  {
651  LOGSYSERROR("tcseattr(%d,TCSANOW,...)", fd);
652  return RC_ERROR;
653  }
654 
655  return OK;
656 }
#define SERDEV_GET_ATTR(attr)
Get I/O defined attribute value.
Definition: serdev.c:249
#define SERDEV_GET_BAUDRATE(baudrate)
Get baudrate defined value.
Definition: serdev.c:305
#define SERDEV_NO_ATTR
Special "No Attribute" value.
Definition: serdev.c:228
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
int SerDevDeassertCTS ( int  fd)

De-assert RTS (clear to send).

Parameters
fdFile descriptor to the opened serial device.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1521 of file serdev.c.

References SerDevAssertCTS(), SerDevAssertRTS(), and SerDevDeassertRTS().

Referenced by SerDevIsInputDataPresent().

1522 {
1523  int status;
1524 
1525  if( ioctl(fd, TIOCMGET, &status) == -1 )
1526  {
1527  LOGSYSERROR("ioctl(%d,TIOCMGET,...)", fd);
1528  return RC_ERROR;
1529  }
1530 
1531  status &= ~TIOCM_CTS;
1532 
1533  if( ioctl(fd, TIOCMSET, &status) == -1 )
1534  {
1535  LOGSYSERROR("ioctl(%d,TIOCMSET,0x%x)", fd, status);
1536  return RC_ERROR;
1537  }
1538 
1539  return OK;
1540 }
int SerDevDeassertRTS ( int  fd)

De-assert RTS (request to send).

Parameters
fdFile descriptor to the opened serial device.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1479 of file serdev.c.

Referenced by SerDevDeassertCTS(), and SerDevIsInputDataPresent().

1480 {
1481  int status;
1482 
1483  if( ioctl(fd, TIOCMGET, &status) == -1 )
1484  {
1485  LOGSYSERROR("ioctl(%d,TIOCMGET,...)", fd);
1486  return RC_ERROR;
1487  }
1488 
1489  status &= ~TIOCM_RTS;
1490 
1491  if( ioctl(fd, TIOCMSET, &status) == -1 )
1492  {
1493  LOGSYSERROR("ioctl(%d,TIOCMSET,0x%x)", fd, status);
1494  return RC_ERROR;
1495  }
1496 
1497  return OK;
1498 }
ssize_t SerDevFIFOInputCount ( int  fd)

Determine the number of bytes in the input FIFO of the serial device.

The input FIFO holds data received but not read.

Parameters
fdFile descriptor to the opened serial device.
Returns
On success, the number of bytes in the input FIFO.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1146 of file serdev.c.

References SERDEV_FIONREAD, SerDevFIFOInputFlush(), SERDEVLOG, SERDEVLOGNL, and SerDevRead().

Referenced by SerDevFIFOInputFlush(), and SerDevIsInputDataPresent().

1147 {
1148  unsigned int nBytes = 0;
1149  int rc;
1150 
1151  rc = ioctl(fd, (unsigned long)SERDEV_FIONREAD, &nBytes);
1152  if( rc == -1 )
1153  {
1154  // not a tty, something is hosed
1155  if( errno != ENOTTY )
1156  {
1157  LOGSYSERROR("ioctl(%d,0x%x,...)", fd, SERDEV_FIONREAD);
1158  return (ssize_t)(RC_ERROR);
1159  }
1160  else
1161  {
1162  return (ssize_t)0;
1163  }
1164  }
1165  else
1166  {
1167  return (ssize_t)nBytes;
1168  }
1169 }
#define SERDEV_FIONREAD
number in input queue
Definition: serdev.c:225
ssize_t SerDevFIFOInputFlush ( int  fd)

Flush the input FIFO buffer, discarding all data in buffer.

The input FIFO holds data received but not read.

This function does not block.

Parameters
fdFile descriptor to the opened serial device.
Returns
The number of bytes flushed.

Definition at line 1202 of file serdev.c.

References SerDevFIFOInputCount().

Referenced by SerDevFIFOInputCount().

1203 {
1204  ssize_t n;
1205 
1206  LOGDIAG4CALL(_TINT(fd));
1207 
1208  n = SerDevFIFOInputCount(fd);
1209 
1210  tcflush(fd, TCIFLUSH);
1211 
1212  return n;
1213 }
ssize_t SerDevFIFOInputCount(int fd)
Determine the number of bytes in the input FIFO of the serial device.
Definition: serdev.c:1146
void SerDevFIFOOutputDrain ( int  fd)

Transmit (drain) all data written to the output FIFO buffer.

The output FIFO holds data written to the device but not transmitted.

This function blocks until all of the FIFO data has been transmitted.

Parameters
fdFile descriptor to the opened serial device.

Definition at line 1223 of file serdev.c.

1224 {
1225  LOGDIAG4CALL(_TINT(fd));
1226 
1227  tcdrain(fd);
1228 }
void SerDevFIFOOutputFlush ( int  fd)

Flush output FIFO buffer, discarding all data in buffer.

The output FIFO holds data written to the device but not transmitted.

This function does not block.

Parameters
fdFile descriptor to the opened serial device.

Definition at line 1216 of file serdev.c.

1217 {
1218  LOGDIAG4CALL(_TINT(fd));
1219 
1220  tcflush(fd, TCOFLUSH);
1221 }
int SerDevGetc ( int  fd,
uint_t  usec 
)

Get 1 character from the serial device.

Read 1 character from the serial device input. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the read can block indefinitely.

Parameters
fdFile descriptor to the opened serial device.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the read.
If usec == 0, then the read will block indefinitely until count bytes are read or an I/O error occurred.
Returns
On success, returns the character read as unsigned char cast to an int.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 843 of file serdev.c.

References fdset_nowarn().

Referenced by SerDevReadLine().

844 {
845  byte_t byte;
846  fd_set rset;
847  struct timeval timeout;
848  int nFd;
849  ssize_t n;
850 
851  LOGDIAG4CALL(_TINT(fd), _TUINT(usec));
852 
853  FD_ZERO(&rset);
854  fdset_nowarn(fd, &rset);
855 
856  // wait for character with timeout
857  if( usec > 0 )
858  {
859  // load timeout
860  timeout.tv_sec = (time_t)(usec / 1000000);
861  timeout.tv_usec = (time_t)(usec % 1000000);
862 
863  nFd = select(fd+1, &rset, NULL, NULL, &timeout);
864  }
865 
866  // block indefinitely for character
867  else
868  {
869  nFd = select(fd+1, &rset, NULL, NULL, NULL);
870  }
871 
872  // system error occurred
873  if( nFd < 0 )
874  {
875  LOGSYSERROR("select(%d,...)", fd);
876  return RC_ERROR;
877  }
878 
879  // select() timeout occurred
880  else if( nFd == 0 )
881  {
882  LOGDIAG4("select() on read timed out");
883  errno = ETIMEDOUT;
884  return RC_ERROR;
885  }
886 
887  // data available from serial device, but error on read
888  else if( (n = read(fd, &byte, (size_t)1)) < 0 )
889  {
890  LOGSYSERROR("read(%d,...)", fd);
891  return RC_ERROR;
892  }
893 
894  // nothing read
895  else if( n == 0 )
896  {
897  LOGERROR("0=read(%d,...)", fd);
898  errno = EIO;
899  return RC_ERROR;
900  }
901 
902  // read character
903  else
904  {
905  LOGDIAG4("%s() byte=0x%02x read", LOGFUNCNAME, byte);
906  return (int)(((uint_t)(byte)) & 0x00ff);
907  }
908 }
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: serdev.c:94
static void SerDevLogBytes ( byte_t  buffer[],
size_t  size,
bool_t  bNewLine 
)
static

Log read/written bytes to log stream.

Parameters
bufferBuffer of bytes.
sizeNumber of bytes in buffer to log.
bNewLineDo [not] output trailing newline.

Definition at line 138 of file serdev.c.

139 {
140  size_t n;
141  FILE *fp;
142  char *sep = " ";
143 
144  if( size == 0 )
145  {
146  return;
147  }
148 
149  fp = LOG_GET_LOGFP();
150 
151  for(n=0; n<size; ++n)
152  {
153  fprintf(fp, "%s0x%02x", sep, buffer[n]);
154  }
155 
156  if( bNewLine )
157  {
158  fprintf(fp, "\n");
159  }
160 }
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.

Parameters
sSerDevNameSerial device port name (e.g. /dev/ttyS0).
nBaudRateBaud rate.
nByteSizeBytes size in bits 5...8.
cParityParity. One of: 'N', 'E', 'O'
nStopBitsNumber of stop bits 1, 2
bRtsCtsDo [not] use hardware flow control.
bXonXoffDo [not] use software flow control.
Returns
On success, a file descriptor(>=0) to the opened serial device.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 663 of file serdev.c.

References SerDevConfigure().

670 {
671  int fd;
672 
673  LOGDIAG4CALL( _TSTR(sSerDevName),
674  _TINT(nBaudRate),
675  _TINT(nByteSize),
676  _TCHAR(cParity),
677  _TINT(nStopBits),
678  _TBOOL(bRtsCts),
679  _TBOOL(bXonXoff) );
680 
681  fd = open(sSerDevName, O_RDWR|O_NONBLOCK|O_NOCTTY);
682 
683  if( fd == -1 )
684  {
685  LOGSYSERROR("open(%s,...)", sSerDevName);
686  return RC_ERROR;
687  }
688 
689  else if( SerDevConfigure(fd, nBaudRate, nByteSize, cParity,
690  nStopBits, bRtsCts, bXonXoff) != OK )
691  {
692  LOGERROR("SerDevConfigure(): failed");
693  close(fd);
694  return RC_ERROR;
695  }
696 
697  else
698  {
699  LOGDIAG4("Serial device %s opened", sSerDevName);
700  return fd;
701  }
702 }
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.
Definition: serdev.c:463
static int SerDevOptAttrCmp ( const void *  pKey1,
const void *  pKey2 
)
inlinestatic

Serial option attribute comparator.

Parameters
pKey1Attribute key 1
pKey2Attribute key 2

Definition at line 258 of file serdev.c.

259 {
260  return strcmp((const char *)pKey1, (const char *)pKey2);
261 }
int SerDevPutc ( int  fd,
byte_t  byte,
uint_t  usec 
)

Put one character to serial device.

Write 1 character to the serial device output. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the write can block indefinitely.

Parameters
fdFile descriptor to the opened serial device.
byteCharacter to write.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the write.
If usec == 0, then the write will block indefinitely until count bytes are written or an I/O error occurred.
Returns
On success, returns the character written as unsigned char cast to an int.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 910 of file serdev.c.

References fdset_nowarn().

911 {
912  fd_set wset;
913  struct timeval timeout;
914  int nFd;
915  ssize_t n;
916 
917  LOGDIAG4CALL(_TINT(fd), _THEX(byte), _TUINT(usec));
918 
919  FD_ZERO(&wset);
920  fdset_nowarn(fd, &wset);
921 
922  // wait for output with timeout
923  if( usec > 0 )
924  {
925  // load timeout (gets munged after each select())
926  timeout.tv_sec = (time_t)(usec / 1000000);
927  timeout.tv_usec = (time_t)(usec % 1000000);
928 
929  nFd = select(fd+1, NULL, &wset, NULL, &timeout);
930  }
931 
932  // block indefinitely for output
933  else
934  {
935  nFd = select(fd+1, NULL, &wset, NULL, NULL);
936  }
937 
938  // system error occurred
939  if( nFd < 0 )
940  {
941  LOGSYSERROR("select(%d,...)", fd);
942  return RC_ERROR;
943  }
944 
945  // select() timeout occurred
946  else if( nFd == 0 )
947  {
948  LOGDIAG4("select() on write timed out");
949  errno = ETIMEDOUT;
950  return RC_ERROR;
951  }
952 
953  // data available from serial device (but error on write)
954  else if( (n = write(fd, &byte, (size_t)1)) < 0 )
955  {
956  LOGSYSERROR("write(%d,...)", fd);
957  return RC_ERROR;
958  }
959 
960  // nothing written
961  else if( n == 0 )
962  {
963  LOGERROR("0=write(%d,...)", fd);
964  errno = EIO;
965  return RC_ERROR;
966  }
967 
968  // character written
969  else
970  {
971  LOGDIAG4("%s() byte=0x%02x written", LOGFUNCNAME, byte);
972  return (int)(((uint_t)(byte)) & 0x00ff);
973  }
974 }
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: serdev.c:94
ssize_t SerDevRead ( int  fd,
byte_t *  buffer,
size_t  count,
uint_t  usec 
)

Read from the serial device.

Read up to count bytes into buffer from the serial device input. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the read can block indefinitely.

Note the the bytes read can be less than the count.

Parameters
fdFile descriptor to the opened serial device.
bufferOutput read buffer.
countNumber of bytes to read.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the read.
If usec == 0, then the read will block indefinitely until count bytes are read or an I/O error occurred.
Returns
On success, the number of bytes read into buffer.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 976 of file serdev.c.

References fdset_nowarn(), SERDEVLOG, timer_elapsed(), and timer_mark().

Referenced by SerDevFIFOInputCount().

977 {
978  bool_t bNonBlocking;
979  ssize_t nBytes = 0;
980  struct timeval tstart;
981  uint_t tdelta;
982  fd_set rset;
983  struct timeval timeout;
984  int nFd;
985  ssize_t n;
986 
987  LOGDIAG4CALL(_TINT(fd), _TPTR(buffer), _TUINT(count), _TUINT(usec));
988 
989  bNonBlocking = usec > 0? true: false;
990 
991  while( nBytes < count )
992  {
993  FD_ZERO(&rset);
994  fdset_nowarn(fd, &rset);
995 
996  // wait for input with timeout
997  if( bNonBlocking )
998  {
999  timer_mark(&tstart);
1000 
1001  // (re)load timeout (gets munged after each select())
1002  timeout.tv_sec = (time_t)(usec / 1000000);
1003  timeout.tv_usec = (time_t)(usec % 1000000);
1004 
1005  nFd = select(fd+1, &rset, NULL, NULL, &timeout);
1006  }
1007  // block indefinitely for input
1008  else
1009  {
1010  nFd = select(fd+1, &rset, NULL, NULL, NULL);
1011  }
1012 
1013  // system error occurred
1014  if( nFd < 0 )
1015  {
1016  LOGSYSERROR("select(%d,...)", fd);
1017  return (ssize_t)(RC_ERROR);
1018  }
1019 
1020  // select() timeout occurred
1021  else if( nFd == 0 )
1022  {
1023  LOGDIAG4("select() on read timed out");
1024  }
1025 
1026  // data available from serial device (but error on read)
1027  else if( (n = read(fd, buffer+nBytes, count-(size_t)nBytes)) < 0 )
1028  {
1029  LOGSYSERROR("read(%d,...)", fd);
1030  return (ssize_t)(RC_ERROR);
1031  }
1032 
1033  // read some data
1034  else
1035  {
1036  nBytes += n;
1037  }
1038 
1039  // determine time left for non-blocking read timeout
1040  if( (nBytes < count) && bNonBlocking )
1041  {
1042  tdelta = timer_elapsed(&tstart);
1043  if( tdelta >= usec )
1044  {
1045  LOGDIAG4("%s() timed out", LOGFUNCNAME);
1046  break;
1047  }
1048  else
1049  {
1050  usec -= tdelta;
1051  }
1052  }
1053  }
1054 
1055  LOGDIAG4("%s() %lu bytes read", LOGFUNCNAME, nBytes);
1056  SERDEVLOG(buffer, (size_t)nBytes, true);
1057 
1058  return nBytes;
1059 }
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: serdev.c:94
#define SERDEVLOG(buffer, size, bNewLine)
Log read/written bytes to log stream.
Definition: serdev.c:113
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: serdev.c:174
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
Definition: serdev.c:192
ssize_t SerDevReadLine ( int  fd,
char  buffer[],
size_t  count,
char *  eol,
uint_t  usec 
)

Read a ASCII character line from the serial device.

Read up to count bytes into buffer from the serial device input. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the read can block indefinitely.

The end-of-line sequence defines the end of the line. It is stripped from the return buffer.

Parameters
fdFile descriptor to the opened serial device.
[out]bufferOutput read buffer.
countNumber of bytes to read.
eolEnd-of-line character sequence > 0.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the read.
If usec == 0, then the read will block indefinitely until count bytes are read or an I/O error occurred.
Returns
On success, the number of bytes read into buffer.
On failure, errno is set and RC_ERROR(-1) is returned.
In either case, the buffer is guaranteed to be NULL terminated.

Definition at line 720 of file serdev.c.

References SerDevGetc(), timer_elapsed(), and timer_mark().

725 {
726  struct timeval tstart; // start of read line
727  uint_t tdelta; // read delta time
728  int c; // received character
729  ssize_t len = 0; // length of line sans eol sequence
730  bool_t bInEol = false; // [not] in end-of-line state
731  char *sSave = eol; // save eol pointer
732 
733  buffer[0] = 0;
734 
735  // must have an end-of-line termination sequence
736  if( (eol == NULL) || (*eol == 0) )
737  {
738  LOGERROR("No end-of-line sequence specified.");
739  return RC_ERROR;
740  }
741 
742  // start
743  timer_mark(&tstart);
744 
745  //
746  // Read until the end of the end-of-line sequence or an error has occurred.
747  //
748  while( len < count-1 )
749  {
750  // read character
751  c = SerDevGetc(fd, usec);
752 
753  // read error occurred
754  if( c < 0 )
755  {
756  buffer[len] = 0;
757  return RC_ERROR;
758  }
759 
760  // end-of-line sequence
761  else if( c == *eol )
762  {
763  // start of eol
764  if( !bInEol )
765  {
766  buffer[len] = 0;
767  bInEol = true;
768  }
769 
770  ++eol;
771 
772  // got a full line
773  if( *eol == 0 )
774  {
775  return len;
776  }
777  }
778 
779  // unexpected character in end-of-line sequence
780  else if( bInEol )
781  {
782  LOGWARN("Unexpected character '%c' found in end-of-line sequence \"%s\".",
783  c, sSave);
784  return len;
785  }
786 
787  // normal character
788  else
789  {
790  buffer[len++] = (char)c;
791  }
792 
793  // delta time
794  tdelta = timer_elapsed(&tstart);
795 
796  // timed out
797  if( (usec > 0) && (tdelta >= usec) )
798  {
799  LOGDIAG4("%s() timed out", LOGFUNCNAME);
800  buffer[len] = 0;
801  return RC_ERROR;
802  }
803  }
804 
805  buffer[len] = 0;
806 
807  LOGERROR("Line > %zu characters long.", count);
808 
809  return RC_ERROR;
810 }
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: serdev.c:174
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
Definition: serdev.c:192
int SerDevGetc(int fd, uint_t usec)
Get 1 character from the serial device.
Definition: serdev.c:843
int SerDevSetBaudRate ( int  fd,
int  nBaudRate 
)

Set the baudrate.

Parameters
fdFile descriptor to the opened serial device.
nBaudRateBaud rate.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1230 of file serdev.c.

References SERDEV_GET_BAUDRATE, and SERDEV_NO_ATTR.

Referenced by SerDevIsInputDataPresent().

1231 {
1232  struct termios tios;
1233  speed_t ospeed, ispeed;
1234 
1235  LOGDIAG4CALL(_TINT(fd), _TINT(nBaudRate));
1236 
1237  // get the current device attributes
1238  if( tcgetattr(fd, &tios) == -1 )
1239  {
1240  LOGSYSERROR("tcgetattr(%d,...) failed", fd);
1241  return RC_ERROR;
1242  }
1243 
1244  // set up baudrate
1245  if((ospeed = SERDEV_GET_BAUDRATE(nBaudRate)) == SERDEV_NO_ATTR)
1246  {
1247  LOGERROR("Invalid/unsupported baud rate: %u", nBaudRate);
1248  errno = EINVAL;
1249  return RC_ERROR;
1250  }
1251  ispeed = ospeed;
1252  if( cfsetospeed(&tios, ospeed) == -1 ) // set output baudrate in structure
1253  {
1254  LOGSYSERROR("tcsetospeed(tios,%u)", ospeed);
1255  return RC_ERROR;
1256  }
1257  if( cfsetispeed(&tios, ispeed) == -1 ) // set input baudrate in structure
1258  {
1259  LOGSYSERROR("tcsetispeed(tios,%u)", ispeed);
1260  return RC_ERROR;
1261  }
1262 
1263  return OK;
1264 }
#define SERDEV_GET_BAUDRATE(baudrate)
Get baudrate defined value.
Definition: serdev.c:305
#define SERDEV_NO_ATTR
Special "No Attribute" value.
Definition: serdev.c:228
int SerDevSetByteSize ( int  fd,
int  nByteSize 
)

Set the byte size.

Parameters
fdFile descriptor to the opened serial device.
nByteSizeBytes size in bits 5...8.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1266 of file serdev.c.

References NOTBITS.

Referenced by SerDevIsInputDataPresent().

1267 {
1268  struct termios tios;
1269 
1270  LOGDIAG4CALL(_TINT(fd), _TINT(nByteSize));
1271 
1272  // set up data character size (bits)
1273  tios.c_cflag &= NOTBITS(CSIZE);
1274  switch( nByteSize )
1275  {
1276  case 8:
1277  tios.c_cflag |= CS8;
1278  break;
1279  case 7:
1280  tios.c_cflag |= CS7;
1281  break;
1282  case 6:
1283  tios.c_cflag |= CS6;
1284  break;
1285  case 5:
1286  tios.c_cflag |= CS5;
1287  break;
1288  default:
1289  LOGERROR("Invalid data byte size: %u", nByteSize);
1290  errno = EINVAL;
1291  return RC_ERROR;
1292  }
1293 
1294  return OK;
1295 }
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
int SerDevSetHwFlowControl ( int  fd,
bool_t  bRtsCts 
)

Set hardware flow control state.

Parameters
fdFile descriptor to the opened serial device.
bRtsCtsDo [not] use hardware flow control.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1350 of file serdev.c.

References NOTBITS, SERDEV_GET_ATTR, and SERDEV_NO_ATTR.

Referenced by SerDevIsInputDataPresent().

1351 {
1352  struct termios tios;
1353  unsigned int attr;
1354 
1355  LOGDIAG4CALL(_TINT(fd), _TBOOL(bRtsCts));
1356 
1357  // get the current device attributes
1358  if( tcgetattr(fd, &tios) == -1 )
1359  {
1360  LOGSYSERROR("tcgetattr(%d,...) failed", fd);
1361  return RC_ERROR;
1362  }
1363 
1364  // set up rts/cts hardware flow control
1365  if( (attr = SERDEV_GET_ATTR(CRTSCTS)) != SERDEV_NO_ATTR )
1366  {
1367  if( bRtsCts )
1368  {
1369  tios.c_cflag |= (CRTSCTS);
1370  }
1371  else
1372  {
1373  tios.c_cflag &= NOTBITS(CRTSCTS);
1374  }
1375  }
1376  // try it with alternate constant name
1377  else if( (attr = SERDEV_GET_ATTR(CNEW_RTSCTS)) != SERDEV_NO_ATTR )
1378  {
1379  if( bRtsCts )
1380  {
1381  tios.c_cflag |= (attr);
1382  }
1383  else
1384  {
1385  tios.c_cflag &= NOTBITS(attr);
1386  }
1387  }
1388  else
1389  {
1390  LOGDIAG4("Do not know how to set/clear RTS/CTS hardware flow control.");
1391  return RC_ERROR;
1392  }
1393 
1394  // flush data
1395  if( tcflush(fd, TCIOFLUSH) == -1 )
1396  {
1397  LOGSYSERROR("tcflush(%d,TCIOFLUSH)", fd);
1398  }
1399 
1400  // set hw flow control
1401  if( tcsetattr(fd, TCSANOW, &tios) == -1 )
1402  {
1403  LOGSYSERROR("tcseattr(%d,TCSANOW,...)", fd);
1404  return RC_ERROR;
1405  }
1406 
1407  return OK;
1408 }
#define SERDEV_GET_ATTR(attr)
Get I/O defined attribute value.
Definition: serdev.c:249
#define SERDEV_NO_ATTR
Special "No Attribute" value.
Definition: serdev.c:228
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
int SerDevSetParity ( int  fd,
int  cParity 
)

Set the parity.

Parameters
fdFile descriptor to the opened serial device.
cParityParity. One of: 'N', 'E', 'O'
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1297 of file serdev.c.

References NOTBITS.

Referenced by SerDevIsInputDataPresent().

1298 {
1299  struct termios tios;
1300 
1301  LOGDIAG4CALL(_TINT(fd), _TCHAR(cParity));
1302 
1303  // set up parity
1304  tios.c_iflag &= NOTBITS(INPCK|ISTRIP);
1305  switch( cParity )
1306  {
1307  case 'N':
1308  tios.c_cflag &= NOTBITS(PARENB|PARODD);
1309  break;
1310  case 'E':
1311  tios.c_cflag &= NOTBITS(PARODD);
1312  tios.c_cflag |= (PARENB);
1313  break;
1314  case 'O':
1315  tios.c_cflag |= (PARENB|PARODD);
1316  break;
1317  default:
1318  LOGERROR("Invalid parity: %c", cParity);
1319  errno = EINVAL;
1320  return RC_ERROR;
1321  }
1322 
1323  return OK;
1324 }
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
int SerDevSetStopBits ( int  fd,
int  nStopBitgs 
)

Set the number of stop bits.

Parameters
fdFile descriptor to the opened serial device.
nStopBitsNumber of stop bits 1, 2
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1326 of file serdev.c.

References NOTBITS.

Referenced by SerDevIsInputDataPresent().

1327 {
1328  struct termios tios;
1329 
1330  LOGDIAG4CALL(_TINT(fd), _TINT(nStopBits));
1331 
1332  // set up stopbits
1333  switch( nStopBits )
1334  {
1335  case 1:
1336  tios.c_cflag &= NOTBITS(CSTOPB);
1337  break;
1338  case 2:
1339  tios.c_cflag |= (CSTOPB);
1340  break;
1341  default:
1342  LOGERROR("Invalid number of stop bits: %u", nStopBits);
1343  errno = EINVAL;
1344  return RC_ERROR;
1345  }
1346 
1347  return OK;
1348 }
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
int SerDevSetSwFlowControl ( int  fd,
bool_t  bXonXoff 
)

Set software flow control state.

Parameters
fdFile descriptor to the opened serial device.
bXonXoffDo [not] use software flow control.
Returns
Returns OK(0) on success.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1410 of file serdev.c.

References NOTBITS, SERDEV_GET_ATTR, and SERDEV_NO_ATTR.

Referenced by SerDevIsInputDataPresent().

1411 {
1412  struct termios tios;
1413  unsigned int attr;
1414 
1415  LOGDIAG4CALL(_TINT(fd), _TBOOL(bXonXoff));
1416 
1417  // get the current device attributes
1418  if( tcgetattr(fd, &tios) == -1 )
1419  {
1420  LOGSYSERROR("tcgetattr(%d,...) failed", fd);
1421  return RC_ERROR;
1422  }
1423 
1424  // set up xon/xoff software flow control
1425  if( (attr = SERDEV_GET_ATTR(IXANY)) != SERDEV_NO_ATTR )
1426  {
1427  if( bXonXoff )
1428  {
1429  tios.c_iflag |= (IXON|IXOFF); // |IXANY)
1430  }
1431  else
1432  {
1433  tios.c_iflag &= NOTBITS(IXON|IXOFF|IXANY);
1434  }
1435  }
1436  else
1437  {
1438  if( bXonXoff )
1439  {
1440  tios.c_iflag |= (IXON|IXOFF);
1441  }
1442  else
1443  {
1444  tios.c_iflag &= NOTBITS(IXON|IXOFF);
1445  }
1446  }
1447 
1448  // set sw flow control
1449  if( tcsetattr(fd, TCSANOW, &tios) == -1 )
1450  {
1451  LOGSYSERROR("tcseattr(%d,TCSANOW,...)", fd);
1452  return RC_ERROR;
1453  }
1454 
1455  return OK;
1456 }
#define SERDEV_GET_ATTR(attr)
Get I/O defined attribute value.
Definition: serdev.c:249
#define SERDEV_NO_ATTR
Special "No Attribute" value.
Definition: serdev.c:228
#define NOTBITS(bits)
Bitwise complement.
Definition: serdev.c:86
ssize_t SerDevWrite ( int  fd,
byte_t *  buffer,
size_t  count,
uint_t  usec 
)

Write to serial device.

Write up to count bytes from the buffer to the serial device output. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the write can block indefinitely.

Note that the number of bytes written can be less than the count.

Parameters
fdFile descriptor to the opened serial device.
bufferInput write buffer.
countNumber of of bytes to write.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the write.
If usec == 0, then the write will block indefinitely until count bytes are written or an I/O error occurred.
Returns
On success, the number of bytes written is returned.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 1061 of file serdev.c.

References fdset_nowarn(), SERDEVLOG, timer_elapsed(), and timer_mark().

Referenced by SerDevWriteLine().

1062 {
1063  bool_t bNonBlocking;
1064  ssize_t nBytes = 0;
1065  struct timeval tstart;
1066  uint_t tdelta;
1067  fd_set wset;
1068  struct timeval timeout;
1069  int nFd;
1070  ssize_t n;
1071 
1072  LOGDIAG4CALL(_TINT(fd), _TPTR(buffer), _TUINT(count), _TUINT(usec));
1073 
1074  bNonBlocking = usec > 0? true: false;
1075 
1076  while( nBytes < count )
1077  {
1078  FD_ZERO(&wset);
1079  fdset_nowarn(fd, &wset);
1080 
1081  // wait for output with timeout
1082  if( bNonBlocking )
1083  {
1084  timer_mark(&tstart);
1085 
1086  // (re)load timeout (gets munged after each select())
1087  timeout.tv_sec = (time_t)(usec / 1000000);
1088  timeout.tv_usec = (time_t)(usec % 1000000);
1089 
1090  nFd = select(fd+1, NULL, &wset, NULL, &timeout);
1091  }
1092  // block indefinitely for output
1093  else
1094  {
1095  nFd = select(fd+1, NULL, &wset, NULL, NULL);
1096  }
1097 
1098  // system error occurred
1099  if( nFd < 0 )
1100  {
1101  LOGSYSERROR("select(%d,...)", fd);
1102  return (ssize_t)(RC_ERROR);
1103  }
1104 
1105  // select() timeout occurred
1106  else if( nFd == 0 )
1107  {
1108  LOGDIAG4("select() on write timed out");
1109  }
1110 
1111  // data available from serial device (but error on read)
1112  else if( (n = write(fd, buffer+nBytes, count-(size_t)nBytes)) < 0 )
1113  {
1114  LOGSYSERROR("write(%d,...)", fd);
1115  return (ssize_t)(RC_ERROR);
1116  }
1117 
1118  // written some data
1119  else
1120  {
1121  nBytes += n;
1122  }
1123 
1124  // determine time left for non-blocking read timeout
1125  if( (nBytes < count) && bNonBlocking )
1126  {
1127  tdelta = timer_elapsed(&tstart);
1128  if( tdelta >= usec )
1129  {
1130  LOGDIAG4("%s() timed out", LOGFUNCNAME);
1131  break;
1132  }
1133  else
1134  {
1135  usec -= tdelta;
1136  }
1137  }
1138  }
1139 
1140  LOGDIAG4("%s() %lu bytes written", LOGFUNCNAME, nBytes);
1141  SERDEVLOG(buffer, (size_t)nBytes, true);
1142 
1143  return nBytes;
1144 }
static void fdset_nowarn(int fd, fd_set *pset)
FD_SET() wrapper with no annoying warnings.
Definition: serdev.c:94
#define SERDEVLOG(buffer, size, bNewLine)
Log read/written bytes to log stream.
Definition: serdev.c:113
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: serdev.c:174
static uint_t timer_elapsed(struct timeval *pTvMark)
Calculate the elapsed time between the given time mark and this call.
Definition: serdev.c:192
ssize_t SerDevWriteLine ( int  fd,
char *  buffer,
char *  eol,
uint_t  usec 
)

Write null-terminated ASCII character line to serial device.

Write line plus end-of-line sequence. This call is non-blocking if the timeout value usec is greater than zero. Otherwise the write can block indefinitely.

Parameters
fdFile descriptor to the opened serial device.
[in]bufferBuffer to write.
eolEnd-of-line character sequence to append to buffer output.
usecTimeout in microseconds.
If usec > 0, an upper timeout limit is placed on the write.
If usec == 0, then the write will block indefinitely until count bytes are written or an I/O error occurred.
Returns
On success, the number of bytes written is returned.
On failure, errno is set and RC_ERROR(-1) is returned.

Definition at line 812 of file serdev.c.

References SerDevWrite().

816 {
817  size_t lenBuf, lenEol;
818  ssize_t m, n;
819 
820  // must have an end-of-line termination sequence
821  if( (eol == NULL) || (*eol == 0) )
822  {
823  LOGERROR("No end-of-line sequence specified.");
824  return RC_ERROR;
825  }
826 
827  lenBuf = strlen(buffer);
828  lenEol = strlen(eol);
829 
830  m = SerDevWrite(fd, (byte_t *)buffer, lenBuf, usec);
831  n = SerDevWrite(fd, (byte_t *)eol, lenEol, usec);
832 
833  if( (m == lenBuf) && (n == lenEol) )
834  {
835  return m;
836  }
837  else
838  {
839  return RC_ERROR;
840  }
841 }
ssize_t SerDevWrite(int fd, byte_t *buffer, size_t count, uint_t usec)
Write to serial device.
Definition: serdev.c:1061
static uint_t timer_elapsed ( struct timeval *  pTvMark)
static

Calculate the elapsed time between the given time mark and this call.

Parameters
pTvMarkPointer to timeval holding time mark.
Returns
Number of microseconds elasped. If the marked time is invalid or the current time cannot be ascertained, UINT_MAX is returned.

Definition at line 192 of file serdev.c.

References timer_mark().

Referenced by SerDevRead(), SerDevReadLine(), and SerDevWrite().

193 {
194  struct timeval tvEnd, tvDelta;
195 
196  timer_mark(&tvEnd);
197 
198  if( !timerisset(pTvMark) || !timerisset(&tvEnd) )
199  {
200  return UINT_MAX;
201  }
202 
203  tvDelta.tv_sec = tvEnd.tv_sec - pTvMark->tv_sec;
204  if( tvEnd.tv_usec < pTvMark->tv_usec )
205  {
206  tvDelta.tv_sec--;
207  tvEnd.tv_usec += 1000000;
208  }
209  tvDelta.tv_usec = tvEnd.tv_usec - pTvMark->tv_usec;
210 
211  return (uint_t)(tvDelta.tv_sec * 1000000 + tvDelta.tv_usec);
212 }
static void timer_mark(struct timeval *pTvMark)
Mark the current time. Resolution is microseconds.
Definition: serdev.c:174
static void timer_mark ( struct timeval *  pTvMark)
inlinestatic

Mark the current time. Resolution is microseconds.

Parameters
pTvMarkPointer to timeval structure to be populated with the current system seconds and useconds.

Definition at line 174 of file serdev.c.

Referenced by SerDevRead(), SerDevReadLine(), SerDevWrite(), and timer_elapsed().

175 {
176  if( gettimeofday(pTvMark, NULL) != OK )
177  {
178  LOGSYSERROR("gettimeofday()");
179  timerclear(pTvMark);
180  }
181 }

Variable Documentation

SerDevAttrKvp_T SerDevOptAttrTbl[]
static
Initial value:
=
{
{(void *)"*noattr*", 0xffffffff }
}

SerDevOptAttr table. Dynamic method to determine serial device optional defined attributes for each plaform architecture.

Definition at line 268 of file serdev.c.