Skip to content

Commit 0001008

Browse files
yamtxiaoxiang781216
authored andcommitted
drivers/serial/serial.c: adapt to the iovec-based api
This would fix readv/writev issues mentioned in #12674. (only for this specific driver though. with this approach, we basically have to fix every single drivers and filesystems.) Lightly tested on the serial console, using micropython REPL on toywasm with esp32s3-devkit:toywasm, which used to be suffered by the readv issue.
1 parent 30ad31e commit 0001008

File tree

1 file changed

+74
-22
lines changed

1 file changed

+74
-22
lines changed

drivers/serial/serial.c

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ 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);
102104
static int uart_tcdrain(FAR uart_dev_t *dev,
103105
bool cancelable, clock_t timeout);
104106

@@ -110,11 +112,8 @@ static int uart_tcsendbreak(FAR uart_dev_t *dev,
110112

111113
static int uart_open(FAR struct file *filep);
112114
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);
115+
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);
118117
static int uart_ioctl(FAR struct file *filep,
119118
int cmd, unsigned long arg);
120119
static int uart_poll(FAR struct file *filep,
@@ -141,15 +140,15 @@ static const struct file_operations g_serialops =
141140
{
142141
uart_open, /* open */
143142
uart_close, /* close */
144-
uart_read, /* read */
145-
uart_write, /* write */
143+
NULL, /* read */
144+
NULL, /* write */
146145
NULL, /* seek */
147146
uart_ioctl, /* ioctl */
148147
NULL, /* mmap */
149148
NULL, /* truncate */
150149
uart_poll, /* poll */
151-
NULL, /* readv */
152-
NULL /* writev */
150+
uart_readv, /* readv */
151+
uart_writev /* writev */
153152
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
154153
, uart_unlink /* unlink */
155154
#endif
@@ -441,6 +440,50 @@ static inline ssize_t uart_irqwrite(FAR uart_dev_t *dev,
441440
return buflen;
442441
}
443442

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+
444487
/****************************************************************************
445488
* Name: uart_tcdrain
446489
*
@@ -847,11 +890,10 @@ static int uart_close(FAR struct file *filep)
847890
}
848891

849892
/****************************************************************************
850-
* Name: uart_read
893+
* Name: uart_readv
851894
****************************************************************************/
852895

853-
static ssize_t uart_read(FAR struct file *filep,
854-
FAR char *buffer, size_t buflen)
896+
static ssize_t uart_readv(FAR struct file *filep, FAR struct uio *uio)
855897
{
856898
FAR struct inode *inode = filep->f_inode;
857899
FAR uart_dev_t *dev = inode->i_private;
@@ -862,6 +904,7 @@ static ssize_t uart_read(FAR struct file *filep,
862904
#endif
863905
irqstate_t flags;
864906
ssize_t recvd = 0;
907+
ssize_t buflen;
865908
bool echoed = false;
866909
int16_t tail;
867910
char ch;
@@ -885,7 +928,8 @@ static ssize_t uart_read(FAR struct file *filep,
885928
* data from the end of the buffer.
886929
*/
887930

888-
while ((size_t)recvd < buflen)
931+
buflen = uio->uio_resid;
932+
while (recvd < buflen)
889933
{
890934
#ifdef CONFIG_SERIAL_REMOVABLE
891935
/* If the removable device is no longer connected, refuse to read any
@@ -961,7 +1005,8 @@ static ssize_t uart_read(FAR struct file *filep,
9611005
{
9621006
if (recvd > 0)
9631007
{
964-
*buffer-- = '\0';
1008+
static const char zero = '\0';
1009+
uio_copyfrom(uio, recvd, &zero, 1);
9651010
recvd--;
9661011
if (dev->tc_lflag & ECHO)
9671012
{
@@ -990,7 +1035,7 @@ static ssize_t uart_read(FAR struct file *filep,
9901035

9911036
/* Store the received character */
9921037

993-
*buffer++ = ch;
1038+
uio_copyfrom(uio, recvd, &ch, 1);
9941039
recvd++;
9951040

9961041
if (dev->tc_lflag & ECHO)
@@ -1325,19 +1370,24 @@ static ssize_t uart_read(FAR struct file *filep,
13251370
#endif
13261371

13271372
nxmutex_unlock(&dev->recv.lock);
1373+
if (recvd >= 0)
1374+
{
1375+
uio_advance(uio, recvd);
1376+
}
1377+
13281378
return recvd;
13291379
}
13301380

13311381
/****************************************************************************
1332-
* Name: uart_write
1382+
* Name: uart_writev
13331383
****************************************************************************/
13341384

1335-
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer,
1336-
size_t buflen)
1385+
static ssize_t uart_writev(FAR struct file *filep, FAR struct uio *uio)
13371386
{
13381387
FAR struct inode *inode = filep->f_inode;
13391388
FAR uart_dev_t *dev = inode->i_private;
1340-
ssize_t nwritten = buflen;
1389+
ssize_t nwritten;
1390+
ssize_t buflen;
13411391
bool oktoblock;
13421392
int ret;
13431393
char ch;
@@ -1363,12 +1413,14 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer,
13631413
#endif
13641414

13651415
flags = enter_critical_section();
1366-
ret = uart_irqwrite(dev, buffer, buflen);
1416+
ret = uart_irqwritev(dev, uio);
13671417
leave_critical_section(flags);
13681418

13691419
return ret;
13701420
}
13711421

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

13741426
ret = nxmutex_lock(&dev->xmit.lock);
@@ -1408,9 +1460,9 @@ static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer,
14081460
*/
14091461

14101462
uart_disabletxint(dev);
1411-
for (; buflen; buflen--)
1463+
for (; buflen; uio_advance(uio, 1), buflen--)
14121464
{
1413-
ch = *buffer++;
1465+
uio_copyto(uio, 0, &ch, 1);
14141466
ret = OK;
14151467

14161468
/* Do output post-processing */

0 commit comments

Comments
 (0)