diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index d475f44d12075..886f0022b9609 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -115,6 +115,7 @@ static ssize_t uart_read(FAR struct file *filep, static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen); +static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio); static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg); static int uart_poll(FAR struct file *filep, @@ -148,7 +149,7 @@ static const struct file_operations g_serialops = NULL, /* mmap */ NULL, /* truncate */ uart_poll, /* poll */ - NULL, /* readv */ + uart_readv, /* readv */ NULL /* writev */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS , uart_unlink /* unlink */ @@ -850,8 +851,8 @@ static int uart_close(FAR struct file *filep) * Name: uart_read ****************************************************************************/ -static ssize_t uart_read(FAR struct file *filep, - FAR char *buffer, size_t buflen) +static ssize_t uart_read_internal(FAR struct file *filep, FAR char *buffer, + size_t buflen, bool nonblock) { FAR struct inode *inode = filep->f_inode; FAR uart_dev_t *dev = inode->i_private; @@ -1060,7 +1061,7 @@ static ssize_t uart_read(FAR struct file *filep, * return what we have. */ - else if ((filep->f_oflags & O_NONBLOCK) != 0) + else if ((filep->f_oflags & O_NONBLOCK) != 0 || nonblock) { /* If nothing was transferred, then return the -EAGAIN * error (not zero which means end of file). @@ -1102,7 +1103,7 @@ static ssize_t uart_read(FAR struct file *filep, * wait. */ - else if ((filep->f_oflags & O_NONBLOCK) != 0) + else if ((filep->f_oflags & O_NONBLOCK) != 0 || nonblock) { /* Break out of the loop returning -EAGAIN */ @@ -1328,6 +1329,53 @@ static ssize_t uart_read(FAR struct file *filep, return recvd; } +static ssize_t uart_read(FAR struct file *filep, + FAR char *buffer, size_t buflen) +{ + return uart_read_internal(filep, buffer, buflen, false); +} + +/**************************************************************************** + * Name: uart_readv + ****************************************************************************/ + +static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) +{ + FAR const struct iovec *iov = uio->uio_iov; + int iovcnt = uio->uio_iovcnt; + bool nonblock = false; + ssize_t ntotal; + ssize_t nread; + int i; + + for (i = 0, ntotal = 0; i < iovcnt; i++) + { + nread = uart_read_internal(filep, iov[i].iov_base, + iov[i].iov_len, nonblock); + if (nread < 0) + { + return ntotal ? ntotal : nread; + } + + ntotal += nread; + + /* Check for a parital success condition, including an end-of-file */ + + if (nread < iov[i].iov_len) + { + break; + } + + /* set nonblock flag after first read */ + + nonblock = true; + } + + uio_advance(uio, ntotal); + + return ntotal; +} + /**************************************************************************** * Name: uart_write ****************************************************************************/