drivers/serial/pty.c: Add support so that a PTY can poll for both IN/OUT event simultaneously.
This commit is contained in:
parent
38cd556af8
commit
729a65f3ab
@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* drivers/pipes/pipe_common.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2011, 2015-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2008-2009, 2011, 2015-2016, 2018 Gregory Nutt. All
|
||||
* rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -721,17 +722,18 @@ int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
}
|
||||
|
||||
/* Notify the POLLOUT event if the pipe is not full, but only if
|
||||
* there is readers. */
|
||||
* there is readers.
|
||||
*/
|
||||
|
||||
eventset = 0;
|
||||
if (nbytes < (dev->d_bufsize - 1))
|
||||
if ((filep->f_oflags & O_WROK) && (nbytes < (dev->d_bufsize - 1)))
|
||||
{
|
||||
eventset |= POLLOUT;
|
||||
}
|
||||
|
||||
/* Notify the POLLIN event if the pipe is not empty */
|
||||
|
||||
if (nbytes > 0)
|
||||
if ((filep->f_oflags & O_RDOK) && (nbytes > 0))
|
||||
{
|
||||
eventset |= POLLIN;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* drivers/serial/pty.c
|
||||
*
|
||||
* Copyright (C) 2016-2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2016-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -112,10 +112,22 @@
|
||||
|
||||
#undef CONFIG_PSEUDOTERM_FULLBLOCKS
|
||||
|
||||
/* Maximum number of threads than can be waiting for POLL events */
|
||||
|
||||
#ifndef CONFIG_DEV_PTY_NPOLLWAITERS
|
||||
# define CONFIG_DEV_PTY_NPOLLWAITERS 2
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct pty_poll_s
|
||||
{
|
||||
FAR void *src;
|
||||
FAR void *sink;
|
||||
};
|
||||
|
||||
/* This device structure describes on memory of the PTY device pair */
|
||||
|
||||
struct pty_devpair_s;
|
||||
@ -132,6 +144,10 @@ struct pty_dev_s
|
||||
tcflag_t pd_iflag; /* Terminal nput modes */
|
||||
tcflag_t pd_oflag; /* Terminal output modes */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_POLL
|
||||
struct pty_poll_s pd_poll[CONFIG_DEV_PTY_NPOLLWAITERS];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* This structure describes the pipe pair */
|
||||
@ -160,8 +176,10 @@ static void pty_semtake(FAR struct pty_devpair_s *devpair);
|
||||
static void pty_destroy(FAR struct pty_devpair_s *devpair);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||
static int pty_open(FAR struct file *filep);
|
||||
static int pty_close(FAR struct file *filep);
|
||||
#endif
|
||||
static ssize_t pty_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static ssize_t pty_write(FAR struct file *filep, FAR const char *buffer,
|
||||
@ -922,34 +940,81 @@ static int pty_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
{
|
||||
FAR struct inode *inode;
|
||||
FAR struct pty_dev_s *dev;
|
||||
FAR struct pty_devpair_s *devpair;
|
||||
FAR struct pty_poll_s *pollp = NULL;
|
||||
int ret = -ENOSYS;
|
||||
int i;
|
||||
|
||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||
inode = filep->f_inode;
|
||||
dev = inode->i_private;
|
||||
devpair = dev->pd_devpair;
|
||||
|
||||
/* REVISIT: If both POLLIN and POLLOUT are set, might the following logic
|
||||
* fail? Could we not get POLLIN on the sink file and POLLOUT on the source
|
||||
* file?
|
||||
*/
|
||||
pty_semtake(devpair);
|
||||
|
||||
if (setup)
|
||||
{
|
||||
for (i = 0; i < CONFIG_DEV_PTY_NPOLLWAITERS; i++)
|
||||
{
|
||||
if (dev->pd_poll[i].src == NULL && dev->pd_poll[i].sink == NULL)
|
||||
{
|
||||
pollp = &dev->pd_poll[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= CONFIG_DEV_PTY_NPOLLWAITERS)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pollp = (FAR struct pty_poll_s *)fds->priv;
|
||||
}
|
||||
|
||||
/* POLLIN: Data other than high-priority data may be read without blocking. */
|
||||
|
||||
if ((fds->events & POLLIN) != 0)
|
||||
{
|
||||
fds->priv = pollp->src;
|
||||
ret = file_poll(&dev->pd_src, fds, setup);
|
||||
}
|
||||
|
||||
if (ret >= OK || ret == -ENOTTY)
|
||||
{
|
||||
/* POLLOUT: Normal data may be written without blocking. */
|
||||
|
||||
if ((fds->events & POLLOUT) != 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = file_poll(&dev->pd_sink, fds, setup);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
pollp->src = fds->priv;
|
||||
}
|
||||
|
||||
/* POLLOUT: Normal data may be written without blocking. */
|
||||
|
||||
if ((fds->events & POLLOUT) != 0)
|
||||
{
|
||||
fds->priv = pollp->sink;
|
||||
ret = file_poll(&dev->pd_sink, fds, setup);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (pollp->src)
|
||||
{
|
||||
fds->priv = pollp->src;
|
||||
file_poll(&dev->pd_src, fds, false);
|
||||
pollp->src = NULL;
|
||||
}
|
||||
|
||||
goto errout;
|
||||
}
|
||||
pollp->sink = fds->priv;
|
||||
}
|
||||
|
||||
if (setup)
|
||||
{
|
||||
fds->priv = pollp;
|
||||
}
|
||||
|
||||
errout:
|
||||
pty_semgive(devpair);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user