PTY: Fix termios read input processing.. what was I thinking? Also, if some data was read, pty_read() should not block on the empty FIFO.
This commit is contained in:
parent
e0aaa168aa
commit
6194467c13
@ -475,6 +475,7 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
{
|
{
|
||||||
dev->d_rdndx = 0;
|
dev->d_rdndx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
nread++;
|
nread++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,14 @@
|
|||||||
|
|
||||||
#include "pty.h"
|
#include "pty.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Pre-processor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Should never be set... only for comparison to serial.c */
|
||||||
|
|
||||||
|
#undef CONFIG_PSEUDOTERM_FULLBLOCKS
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -180,7 +188,9 @@ static void pty_destroy(FAR struct pty_devpair_s *devpair)
|
|||||||
#endif
|
#endif
|
||||||
(void)unregister_driver(devname);
|
(void)unregister_driver(devname);
|
||||||
|
|
||||||
/* Un-register the master device (/dev/ptyN may have already been unlinked) */
|
/* Un-register the master device (/dev/ptyN may have already been
|
||||||
|
* unlinked).
|
||||||
|
*/
|
||||||
|
|
||||||
snprintf(devname, 16, "/dev/pty%d", (int)devpair->pp_minor);
|
snprintf(devname, 16, "/dev/pty%d", (int)devpair->pp_minor);
|
||||||
(void)unregister_driver(devname);
|
(void)unregister_driver(devname);
|
||||||
@ -377,6 +387,7 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
size_t i;
|
size_t i;
|
||||||
char ch;
|
char ch;
|
||||||
|
int ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||||
@ -398,15 +409,62 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
|
|
||||||
if (dev->pd_iflag & (INLCR | IGNCR | ICRNL))
|
if (dev->pd_iflag & (INLCR | IGNCR | ICRNL))
|
||||||
{
|
{
|
||||||
/* We will transfer one byte at a time, making the appropriae
|
/* We will transfer one byte at a time, making the appropriate
|
||||||
* translations.
|
* translations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ntotal = 0;
|
ntotal = 0;
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
ch = *buffer++;
|
#ifndef CONFIG_PSEUDOTERM_FULLBLOCKS
|
||||||
|
/* This logic should return if the pipe becomes empty after some
|
||||||
|
* bytes were read from the pipe. If we have already read some
|
||||||
|
* data, we use the FIONREAD ioctl to test if there are more bytes
|
||||||
|
* in the pipe.
|
||||||
|
*
|
||||||
|
* There is an inherent race condition in this test, but leaving
|
||||||
|
* a few bytes unnecessarily in the pipe should not be harmful.
|
||||||
|
* (we could lock the scheduler between the test and the
|
||||||
|
* file_read() below if we wanted to eliminate the race)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ntotal > 0)
|
||||||
|
{
|
||||||
|
int nsrc;
|
||||||
|
|
||||||
|
/* Check how many bytes are waiting in the pipe */
|
||||||
|
|
||||||
|
ret = file_ioctl(&dev->pd_src, FIONREAD,
|
||||||
|
(unsigned long)((uintptr_t)&nsrc));
|
||||||
|
if (ret < 0)
|
||||||
|
{
|
||||||
|
ntotal = ret;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Break out of the loop and return ntotal if the pipe is
|
||||||
|
* empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nsrc < 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Read one byte from the source the byte. This call will block
|
||||||
|
* if the source pipe is empty.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nread = file_read(&dev->pd_src, &ch, 1);
|
||||||
|
if (nread < 0)
|
||||||
|
{
|
||||||
|
ntotal = nread;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Perform input processing */
|
||||||
/* \n -> \r or \r -> \n translation? */
|
/* \n -> \r or \r -> \n translation? */
|
||||||
|
|
||||||
if (ch == '\n' && (dev->pd_iflag & INLCR) != 0)
|
if (ch == '\n' && (dev->pd_iflag & INLCR) != 0)
|
||||||
@ -424,17 +482,12 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
|
|
||||||
if (ch != '\r' || (dev->pd_iflag & IGNCR) == 0)
|
if (ch != '\r' || (dev->pd_iflag & IGNCR) == 0)
|
||||||
{
|
{
|
||||||
/* Transfer the byte */
|
|
||||||
|
|
||||||
nread = file_read(&dev->pd_src, &ch, 1);
|
/* Transfer the (possibly translated) character and update the
|
||||||
if (nread < 0)
|
* count of bytes transferred.
|
||||||
{
|
*/
|
||||||
ntotal = nread;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the count of bytes transferred */
|
|
||||||
|
|
||||||
|
*buffer++ = ch;
|
||||||
ntotal++;
|
ntotal++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -442,6 +495,12 @@ static ssize_t pty_read(FAR struct file *filep, FAR char *buffer, size_t len)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
/* NOTE: the source pipe will block is no data is available in
|
||||||
|
* the pipe. Otherwise, it will return data from the pipe. If
|
||||||
|
* there are fewer than 'len' bytes in the, it will return with
|
||||||
|
* ntotal < len.
|
||||||
|
*/
|
||||||
|
|
||||||
ntotal = file_read(&dev->pd_src, buffer, len);
|
ntotal = file_read(&dev->pd_src, buffer, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user