Skip to content

Commit

Permalink
drivers/serial/serial.c: adapt readv api to avoid block on secound re…
Browse files Browse the repository at this point in the history
…ad in readv()

Signed-off-by: chao an <[email protected]>
  • Loading branch information
anchao committed Jan 19, 2025
1 parent db6cd88 commit de2054d
Showing 1 changed file with 58 additions and 5 deletions.
63 changes: 58 additions & 5 deletions drivers/serial/serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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).
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -1328,6 +1329,58 @@ 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)
{
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;
}

uio_advance(uio, ntotal);

return ntotal;
}

/****************************************************************************
* Name: uart_write
****************************************************************************/
Expand Down

0 comments on commit de2054d

Please sign in to comment.