serial: add support for termios timeout to serial_read()

see vsergeev/python-periphery#28, vsergeev/python-periphery#30.
This commit is contained in:
Vanya A. Sergeev
2020-05-28 00:04:13 -05:00
parent 03420b4718
commit e0d8632896
2 changed files with 11 additions and 0 deletions
+2
View File
@@ -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.
+9
View File
@@ -25,6 +25,7 @@
struct serial_handle {
int fd;
bool use_termios_timeout;
struct {
int c_errno;
@@ -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;
}
@@ -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");
@@ -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;
}