Skip to content

Commit 44d8dcf

Browse files
committed
drivers/serial/serial.c: only adapt readv api to avoid block on secound read in readv()
Signed-off-by: chao an <[email protected]>
1 parent 6e509ce commit 44d8dcf

File tree

1 file changed

+71
-72
lines changed

1 file changed

+71
-72
lines changed

drivers/serial/serial.c

Lines changed: 71 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,6 @@ static int uart_putxmitchar(FAR uart_dev_t *dev, int ch,
9999
static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev,
100100
FAR const char *buffer,
101101
size_t buflen);
102-
static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev,
103-
FAR struct uio *uio);
104102
static int uart_tcdrain(FAR uart_dev_t *dev,
105103
bool cancelable, clock_t timeout);
106104

@@ -112,8 +110,12 @@ static int uart_tcsendbreak(FAR uart_dev_t *dev,
112110

113111
static int uart_open(FAR struct file *filep);
114112
static int uart_close(FAR struct file *filep);
113+
static ssize_t uart_read(FAR struct file *filep,
114+
FAR char *buffer, size_t buflen);
115+
static ssize_t uart_write(FAR struct file *filep,
116+
FAR const char *buffer,
117+
size_t buflen);
115118
static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio);
116-
static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio);
117119
static int uart_ioctl(FAR struct file *filep,
118120
int cmd, unsigned long arg);
119121
static int uart_poll(FAR struct file *filep,
@@ -140,15 +142,15 @@ static const struct file_operations g_serialops =
140142
{
141143
uart_open, /* open */
142144
uart_close, /* close */
143-
NULL, /* read */
144-
NULL, /* write */
145+
uart_read, /* read */
146+
uart_write, /* write */
145147
NULL, /* seek */
146148
uart_ioctl, /* ioctl */
147149
NULL, /* mmap */
148150
NULL, /* truncate */
149151
uart_poll, /* poll */
150152
uart_readv, /* readv */
151-
uart_writev /* writev */
153+
NULL /* writev */
152154
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
153155
, uart_unlink /* unlink */
154156
#endif
@@ -440,50 +442,6 @@ static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev,
440442
return buflen;
441443
}
442444

443-
/****************************************************************************
444-
* Name: uart_irqwritev
445-
****************************************************************************/
446-
447-
static inline ssize_t uart_irqwritev(FAR uart_dev_t *dev,
448-
FAR struct uio *uio)
449-
{
450-
ssize_t error = 0;
451-
ssize_t total = 0;
452-
int iovcnt = uio->uio_iovcnt;
453-
int i;
454-
455-
for (i = 0; i < iovcnt; i++)
456-
{
457-
const struct iovec *iov = &uio->uio_iov[i];
458-
if (iov->iov_len == 0)
459-
{
460-
continue;
461-
}
462-
463-
ssize_t written = uart_irqwrite(dev, iov->iov_base, iov->iov_len);
464-
if (written < 0)
465-
{
466-
error = written;
467-
break;
468-
}
469-
470-
if (SSIZE_MAX - total < written)
471-
{
472-
error = -EOVERFLOW;
473-
break;
474-
}
475-
476-
total += written;
477-
}
478-
479-
if (error != 0 && total == 0)
480-
{
481-
return error;
482-
}
483-
484-
return total;
485-
}
486-
487445
/****************************************************************************
488446
* Name: uart_tcdrain
489447
*
@@ -890,10 +848,11 @@ static int uart_close(FAR struct file *filep)
890848
}
891849

892850
/****************************************************************************
893-
* Name: uart_readv
851+
* Name: uart_read
894852
****************************************************************************/
895853

896-
static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
854+
static ssize_t uart_read_internal(FAR struct file *filep, FAR char *buffer,
855+
size_t buflen, bool nonblock)
897856
{
898857
FAR struct inode *inode = filep->f_inode;
899858
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)
904863
#endif
905864
irqstate_t flags;
906865
ssize_t recvd = 0;
907-
ssize_t buflen;
908866
bool echoed = false;
909867
int16_t tail;
910868
char ch;
@@ -928,8 +886,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
928886
* data from the end of the buffer.
929887
*/
930888

931-
buflen = uio->uio_resid;
932-
while (recvd < buflen)
889+
while ((size_t)recvd < buflen)
933890
{
934891
#ifdef CONFIG_SERIAL_REMOVABLE
935892
/* 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)
1005962
{
1006963
if (recvd > 0)
1007964
{
1008-
static const char zero = '\0';
1009-
uio_copyfrom(uio, recvd, &zero, 1);
965+
*buffer-- = '\0';
1010966
recvd--;
1011967
if (dev->tc_lflag & ECHO)
1012968
{
@@ -1035,7 +991,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
1035991

1036992
/* Store the received character */
1037993

1038-
uio_copyfrom(uio, recvd, &ch, 1);
994+
*buffer++ = ch;
1039995
recvd++;
1040996

1041997
if (dev->tc_lflag & ECHO)
@@ -1105,7 +1061,7 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
11051061
* return what we have.
11061062
*/
11071063

1108-
else if ((filep->f_oflags & O_NONBLOCK) != 0)
1064+
else if ((filep->f_oflags & O_NONBLOCK) != 0 || nonblock)
11091065
{
11101066
/* If nothing was transferred, then return the -EAGAIN
11111067
* 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)
11471103
* wait.
11481104
*/
11491105

1150-
else if ((filep->f_oflags & O_NONBLOCK) != 0)
1106+
else if ((filep->f_oflags & O_NONBLOCK) != 0 || nonblock)
11511107
{
11521108
/* Break out of the loop returning -EAGAIN */
11531109

@@ -1370,24 +1326,69 @@ static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
13701326
#endif
13711327

13721328
nxmutex_unlock(&dev->recv.lock);
1373-
if (recvd >= 0)
1329+
return recvd;
1330+
}
1331+
1332+
static ssize_t uart_read(FAR struct file *filep,
1333+
FAR char *buffer, size_t buflen)
1334+
{
1335+
return uart_read_internal(filep, buffer, buflen, false);
1336+
}
1337+
1338+
/****************************************************************************
1339+
* Name: uart_readv
1340+
****************************************************************************/
1341+
1342+
static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
1343+
{
1344+
FAR const struct iovec *iov = uio->uio_iov;
1345+
int iovcnt = uio->uio_iovcnt;
1346+
bool nonblock = !!(filep->f_oflags & O_NONBLOCK);
1347+
ssize_t ntotal;
1348+
ssize_t nread;
1349+
int i;
1350+
1351+
for (i = 0, ntotal = 0; i < iovcnt; i++)
13741352
{
1375-
uio_advance(uio, recvd);
1353+
nread = uart_read_internal(filep, iov[i].iov_base,
1354+
iov[i].iov_len, nonblock);
1355+
if (nread < 0)
1356+
{
1357+
if (ntotal > 0)
1358+
{
1359+
break;
1360+
}
1361+
1362+
return nread;
1363+
}
1364+
1365+
ntotal += nread;
1366+
1367+
/* Check for a parital success condition, including an end-of-file */
1368+
1369+
if (nread < iov[i].iov_len)
1370+
{
1371+
break;
1372+
}
1373+
1374+
/* set nonblock flag after first read */
1375+
1376+
nonblock = true;
13761377
}
13771378

1378-
return recvd;
1379+
return ntotal;
13791380
}
13801381

13811382
/****************************************************************************
1382-
* Name: uart_writev
1383+
* Name: uart_write
13831384
****************************************************************************/
13841385

1385-
static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio)
1386+
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer,
1387+
size_t buflen)
13861388
{
13871389
FAR struct inode *inode = filep->f_inode;
13881390
FAR uart_dev_t *dev = inode->i_private;
1389-
ssize_t nwritten;
1390-
ssize_t buflen;
1391+
ssize_t nwritten = buflen;
13911392
bool oktoblock;
13921393
int ret;
13931394
char ch;
@@ -1413,14 +1414,12 @@ static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio)
14131414
#endif
14141415

14151416
flags = enter_critical_section();
1416-
ret = uart_irqwritev(dev, uio);
1417+
ret = uart_irqwrite(dev, buffer, buflen);
14171418
leave_critical_section(flags);
14181419

14191420
return ret;
14201421
}
14211422

1422-
buflen = nwritten = uio->uio_resid;
1423-
14241423
/* Only one user can access dev->xmit.head at a time */
14251424

14261425
ret = nxmutex_lock(&dev->xmit.lock);
@@ -1460,9 +1459,9 @@ static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio)
14601459
*/
14611460

14621461
uart_disabletxint(dev);
1463-
for (; buflen; uio_advance(uio, 1), buflen--)
1462+
for (; buflen; buflen--)
14641463
{
1465-
uio_copyto(uio, 0, &ch, 1);
1464+
ch = *buffer++;
14661465
ret = OK;
14671466

14681467
/* Do output post-processing */

0 commit comments

Comments
 (0)