diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index f97ea696c9..672a537698 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -26,8 +26,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -1047,9 +1049,22 @@ static ssize_t uart_read(FAR struct file *filep, */ dev->recvwaiting = true; - ret = nxsem_wait(&dev->recvsem); + +#ifdef CONFIG_SERIAL_TERMIOS + dev->minrecv = MIN(buflen - recvd, dev->minread - recvd); + if (dev->timeout) + { + ret = nxsem_tickwait(&dev->recvsem, + DSEC2TICK(dev->timeout)); + } + else +#endif + { + ret = nxsem_wait(&dev->recvsem); + } } + dev->recvwaiting = false; leave_critical_section(flags); /* Was a signal received while waiting for data to be @@ -1078,9 +1093,9 @@ static ssize_t uart_read(FAR struct file *filep, */ #ifdef CONFIG_SERIAL_REMOVABLE - recvd = dev->disconnected ? -ENOTCONN : -EINTR; + recvd = dev->disconnected ? -ENOTCONN : ret; #else - recvd = -EINTR; + recvd = ret; #endif } @@ -1539,6 +1554,10 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) termiosp->c_iflag = dev->tc_iflag; termiosp->c_oflag = dev->tc_oflag; termiosp->c_lflag = dev->tc_lflag; +#ifdef CONFIG_SERIAL_TERMIOS + termiosp->c_cc[VTIME] = dev->timeout; + termiosp->c_cc[VMIN] = dev->minread; +#endif ret = 0; } @@ -1560,6 +1579,10 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg) dev->tc_iflag = termiosp->c_iflag; dev->tc_oflag = termiosp->c_oflag; dev->tc_lflag = termiosp->c_lflag; +#ifdef CONFIG_SERIAL_TERMIOS + dev->timeout = termiosp->c_cc[VTIME]; + dev->minread = termiosp->c_cc[VMIN]; +#endif ret = 0; } break; @@ -1813,6 +1836,11 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev) nxsem_init(&dev->recvsem, 0, 0); nxmutex_init(&dev->polllock); +#ifdef CONFIG_SERIAL_TERMIOS + dev->timeout = 0; + dev->minread = 1; +#endif + /* Register the serial driver */ sinfo("Registering %s\n", path); diff --git a/drivers/serial/serial_dma.c b/drivers/serial/serial_dma.c index 4a47b0862a..4c9c05a676 100644 --- a/drivers/serial/serial_dma.c +++ b/drivers/serial/serial_dma.c @@ -336,7 +336,20 @@ void uart_recvchars_done(FAR uart_dev_t *dev) * incoming data available. */ + if (rxbuf->head >= rxbuf->tail) + { + nbytes = rxbuf->head - rxbuf->tail; + } + else + { + nbytes = rxbuf->size - rxbuf->tail + rxbuf->head; + } + +#ifdef CONFIG_SERIAL_TERMIOS + if (nbytes >= dev->minrecv) +#else if (nbytes) +#endif { uart_datareceived(dev); } diff --git a/drivers/serial/serial_io.c b/drivers/serial/serial_io.c index 0a6d2affe4..e3ea186144 100644 --- a/drivers/serial/serial_io.c +++ b/drivers/serial/serial_io.c @@ -222,7 +222,6 @@ void uart_recvchars(FAR uart_dev_t *dev) /* Add the character to the buffer */ rxbuf->buffer[rxbuf->head] = ch; - nbytes++; /* Increment the head index */ @@ -238,7 +237,20 @@ void uart_recvchars(FAR uart_dev_t *dev) * incoming data available. */ + if (rxbuf->head >= rxbuf->tail) + { + nbytes = rxbuf->head - rxbuf->tail; + } + else + { + nbytes = rxbuf->size - rxbuf->tail + rxbuf->head; + } + +#ifdef CONFIG_SERIAL_TERMIOS + if (nbytes >= dev->minrecv) +#else if (nbytes) +#endif { uart_datareceived(dev); } diff --git a/include/nuttx/serial/serial.h b/include/nuttx/serial/serial.h index e784a9257f..2bc2a02398 100644 --- a/include/nuttx/serial/serial.h +++ b/include/nuttx/serial/serial.h @@ -321,6 +321,12 @@ struct uart_dev_s * retained in the f_priv field of the 'struct file'. */ +#ifdef CONFIG_SERIAL_TERMIOS + uint8_t minrecv; /* Minimum received bytes */ + uint8_t minread; /* c_cc[VMIN] */ + uint8_t timeout; /* c_cc[VTIME] */ +#endif + struct pollfd *fds[CONFIG_SERIAL_NPOLLWAITERS]; };