diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index e29d09add3a29..261a7bcc7f39a 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -99,8 +99,6 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch, static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev, FAR const char *buffer, size_t buflen); -static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev, - FAR struct uio *uio); static int uart_tcdrain(FAR uart_dev_t *dev, bool cancelable, clock_t timeout); @@ -112,8 +110,12 @@ static int uart_tcsendbreak(FAR uart_dev_t *dev, static int uart_open(FAR struct file *filep); static int uart_close(FAR struct file *filep); +static ssize_t uart_read(FAR struct file *filep, + FAR char *buffer, size_t buflen); +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 ssize_t uart_writev(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, @@ -140,15 +142,15 @@ static const struct file_operations g_serialops = { uart_open, /* open */ uart_close, /* close */ - NULL, /* read */ - NULL, /* write */ + uart_read, /* read */ + uart_write, /* write */ NULL, /* seek */ uart_ioctl, /* ioctl */ NULL, /* mmap */ NULL, /* truncate */ uart_poll, /* poll */ uart_readv, /* readv */ - uart_writev /* writev */ + NULL /* writev */ #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS , uart_unlink /* unlink */ #endif @@ -440,50 +442,6 @@ static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev, return buflen; } -/**************************************************************************** - * Name: uart_irqwritev - ****************************************************************************/ - -static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev, - FAR struct uio *uio) -{ - ssize_t error = 0; - ssize_t total = 0; - int iovcnt = uio->uio_iovcnt; - int i; - - for (i = 0; i < iovcnt; i++) - { - const struct iovec *iov = &uio->uio_iov[i]; - if (iov->iov_len == 0) - { - continue; - } - - ssize_t written = uart_irqwrite(dev, iov->iov_base, iov->iov_len); - if (written < 0) - { - error = written; - break; - } - - if (SSIZE_MAX - total < written) - { - error = -EOVERFLOW; - break; - } - - total += written; - } - - if (error != 0 && total == 0) - { - return error; - } - - return total; -} - /**************************************************************************** * Name: uart_tcdrain * @@ -890,10 +848,11 @@ static int uart_close(FAR struct file *filep) } /**************************************************************************** - * Name: uart_readv + * Name: uart_read_internal ****************************************************************************/ -static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) +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; @@ -904,7 +863,6 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) #endif irqstate_t flags; ssize_t recvd = 0; - ssize_t buflen; bool echoed = false; int16_t tail; char ch; @@ -928,8 +886,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) * data from the end of the buffer. */ - buflen = uio->uio_resid; - while (recvd < buflen) + while ((size_t)recvd < buflen) { #ifdef CONFIG_SERIAL_REMOVABLE /* If the removable device is no longer connected, refuse to read any @@ -1005,8 +962,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) { if (recvd > 0) { - static const char zero = '\0'; - uio_copyfrom(uio, recvd, &zero, 1); + *buffer-- = '\0'; recvd--; if (dev->tc_lflag & ECHO) { @@ -1035,7 +991,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) /* Store the received character */ - uio_copyfrom(uio, recvd, &ch, 1); + *buffer++ = ch; recvd++; if (dev->tc_lflag & ECHO) @@ -1105,7 +1061,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) * return what we have. */ - else if ((filep->f_oflags & O_NONBLOCK) != 0) + else if (nonblock) { /* If nothing was transferred, then return the -EAGAIN * error (not zero which means end of file). @@ -1147,7 +1103,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) * wait. */ - else if ((filep->f_oflags & O_NONBLOCK) != 0) + else if (nonblock) { /* Break out of the loop returning -EAGAIN */ @@ -1370,24 +1326,70 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio) #endif nxmutex_unlock(&dev->recv.lock); - if (recvd >= 0) + return recvd; +} + +static ssize_t uart_read(FAR struct file *filep, + FAR char *buffer, size_t buflen) +{ + return uart_read_internal(filep, buffer, buflen, + !!(filep->f_oflags & O_NONBLOCK)); +} + +/**************************************************************************** + * 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 = !!(filep->f_oflags & O_NONBLOCK); + ssize_t ntotal; + ssize_t nread; + int i; + + for (i = 0, ntotal = 0; i < iovcnt; i++) { - uio_advance(uio, recvd); + nread = uart_read_internal(filep, iov[i].iov_base, + iov[i].iov_len, nonblock); + if (nread < 0) + { + if (ntotal > 0) + { + break; + } + + return 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; } - return recvd; + return ntotal; } /**************************************************************************** - * Name: uart_writev + * Name: uart_write ****************************************************************************/ -static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio) +static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) { FAR struct inode *inode = filep->f_inode; FAR uart_dev_t *dev = inode->i_private; - ssize_t nwritten; - ssize_t buflen; + ssize_t nwritten = buflen; bool oktoblock; int ret; char ch; @@ -1413,14 +1415,12 @@ static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio) #endif flags = enter_critical_section(); - ret = uart_irqwritev(dev, uio); + ret = uart_irqwrite(dev, buffer, buflen); leave_critical_section(flags); return ret; } - buflen = nwritten = uio->uio_resid; - /* Only one user can access dev->xmit.head at a time */ ret = nxmutex_lock(&dev->xmit.lock); @@ -1460,9 +1460,9 @@ static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio) */ uart_disabletxint(dev); - for (; buflen; uio_advance(uio, 1), buflen--) + for (; buflen; buflen--) { - uio_copyto(uio, 0, &ch, 1); + ch = *buffer++; ret = OK; /* Do output post-processing */ diff --git a/fs/vfs/fs_read.c b/fs/vfs/fs_read.c index 5ae13b57cd405..e1eaf6fbcb41e 100644 --- a/fs/vfs/fs_read.c +++ b/fs/vfs/fs_read.c @@ -182,7 +182,7 @@ ssize_t file_readv(FAR struct file *filep, else if (inode != NULL && inode->u.i_ops) { - if (inode->u.i_ops->readv) + if (iovcnt > 1 && inode->u.i_ops->readv) { struct uio uio; diff --git a/fs/vfs/fs_write.c b/fs/vfs/fs_write.c index 89b5cddd910fd..409d80b6c08e5 100644 --- a/fs/vfs/fs_write.c +++ b/fs/vfs/fs_write.c @@ -160,7 +160,7 @@ ssize_t file_writev(FAR struct file *filep, inode = filep->f_inode; if (inode != NULL && inode->u.i_ops) { - if (inode->u.i_ops->writev) + if (iovcnt > 1 && inode->u.i_ops->writev) { struct uio uio;