Skip to content

Commit

Permalink
serial: add support for termios timeout to serial_read()
Browse files Browse the repository at this point in the history
  • Loading branch information
vsergeev committed May 28, 2020
1 parent 03420b4 commit e0d8632
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/serial.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ Read up to `len` number of bytes from the serial port into the `buf` buffer with
For a non-blocking or timeout-bound read, `serial_read()` may return less than the requested number of bytes.
For a blocking read with the VMIN setting configured, `serial_read()` will block until at least VMIN bytes are read. For a blocking read with both VMIN and VTIME settings configured, `serial_read()` will block until at least VMIN bytes are read or the VTIME interbyte timeout expires after the last byte read. In either case, `serial_read()` may return less than the requested number of bytes.
`serial` should be a valid pointer to a Serial handle opened with `serial_open()` or `serial_open_advanced()`. `timeout_ms` can be positive for a blocking read with a timeout in milliseconds, zero for a non-blocking read, or negative for a blocking read.
Returns the number of bytes read on success, 0 on timeout, or a negative [Serial error code](#return-value) on failure.
Expand Down
9 changes: 9 additions & 0 deletions src/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

struct serial_handle {
int fd;
bool use_termios_timeout;

struct {
int c_errno;
Expand Down Expand Up @@ -234,6 +235,8 @@ int serial_open_advanced(serial_t *serial, const char *path, uint32_t baudrate,
return _serial_error(serial, SERIAL_ERROR_CONFIGURE, errsv, "Setting serial port attributes");
}

serial->use_termios_timeout = false;

return 0;
}

Expand Down Expand Up @@ -261,6 +264,10 @@ int serial_read(serial_t *serial, uint8_t *buf, size_t len, int timeout_ms) {
if ((ret = read(serial->fd, buf + bytes_read, len - bytes_read)) < 0)
return _serial_error(serial, SERIAL_ERROR_IO, errno, "Reading serial port");

/* If we're using VMIN or VMIN+VTIME semantics for end of read, return now */
if (serial->use_termios_timeout)
return ret;

/* Empty read */
if (ret == 0 && len != 0)
return _serial_error(serial, SERIAL_ERROR_IO, 0, "Reading serial port: unexpected empty read");
Expand Down Expand Up @@ -576,6 +583,8 @@ int serial_set_vmin(serial_t *serial, unsigned int vmin) {
if (tcsetattr(serial->fd, TCSANOW, &termios_settings) < 0)
return _serial_error(serial, SERIAL_ERROR_CONFIGURE, errno, "Setting serial port attributes");

serial->use_termios_timeout = vmin > 0;

return 0;
}

Expand Down

0 comments on commit e0d8632

Please sign in to comment.