mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
drivers/serial/pty.c: Add support so that a PTY can poll for both IN/OUT event simultaneously.
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* drivers/pipes/pipe_common.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
/* Notify the POLLOUT event if the pipe is not full, but only if
|
||||||
* there is readers. */
|
* there is readers.
|
||||||
|
*/
|
||||||
|
|
||||||
eventset = 0;
|
eventset = 0;
|
||||||
if (nbytes < (dev->d_bufsize - 1))
|
if ((filep->f_oflags & O_WROK) && (nbytes < (dev->d_bufsize - 1)))
|
||||||
{
|
{
|
||||||
eventset |= POLLOUT;
|
eventset |= POLLOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Notify the POLLIN event if the pipe is not empty */
|
/* Notify the POLLIN event if the pipe is not empty */
|
||||||
|
|
||||||
if (nbytes > 0)
|
if ((filep->f_oflags & O_RDOK) && (nbytes > 0))
|
||||||
{
|
{
|
||||||
eventset |= POLLIN;
|
eventset |= POLLIN;
|
||||||
}
|
}
|
||||||
|
|||||||
+78
-13
@@ -1,7 +1,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* drivers/serial/pty.c
|
* 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>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -112,10 +112,22 @@
|
|||||||
|
|
||||||
#undef CONFIG_PSEUDOTERM_FULLBLOCKS
|
#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
|
* Private Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct pty_poll_s
|
||||||
|
{
|
||||||
|
FAR void *src;
|
||||||
|
FAR void *sink;
|
||||||
|
};
|
||||||
|
|
||||||
/* This device structure describes on memory of the PTY device pair */
|
/* This device structure describes on memory of the PTY device pair */
|
||||||
|
|
||||||
struct pty_devpair_s;
|
struct pty_devpair_s;
|
||||||
@@ -132,6 +144,10 @@ struct pty_dev_s
|
|||||||
tcflag_t pd_iflag; /* Terminal nput modes */
|
tcflag_t pd_iflag; /* Terminal nput modes */
|
||||||
tcflag_t pd_oflag; /* Terminal output modes */
|
tcflag_t pd_oflag; /* Terminal output modes */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_POLL
|
||||||
|
struct pty_poll_s pd_poll[CONFIG_DEV_PTY_NPOLLWAITERS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure describes the pipe pair */
|
/* 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);
|
static void pty_destroy(FAR struct pty_devpair_s *devpair);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
|
||||||
static int pty_open(FAR struct file *filep);
|
static int pty_open(FAR struct file *filep);
|
||||||
static int pty_close(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,
|
static ssize_t pty_read(FAR struct file *filep, FAR char *buffer,
|
||||||
size_t buflen);
|
size_t buflen);
|
||||||
static ssize_t pty_write(FAR struct file *filep, FAR const char *buffer,
|
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 inode *inode;
|
||||||
FAR struct pty_dev_s *dev;
|
FAR struct pty_dev_s *dev;
|
||||||
|
FAR struct pty_devpair_s *devpair;
|
||||||
|
FAR struct pty_poll_s *pollp = NULL;
|
||||||
int ret = -ENOSYS;
|
int ret = -ENOSYS;
|
||||||
|
int i;
|
||||||
|
|
||||||
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
DEBUGASSERT(filep != NULL && filep->f_inode != NULL);
|
||||||
inode = filep->f_inode;
|
inode = filep->f_inode;
|
||||||
dev = inode->i_private;
|
dev = inode->i_private;
|
||||||
|
devpair = dev->pd_devpair;
|
||||||
|
|
||||||
/* REVISIT: If both POLLIN and POLLOUT are set, might the following logic
|
pty_semtake(devpair);
|
||||||
* fail? Could we not get POLLIN on the sink file and POLLOUT on the source
|
|
||||||
* file?
|
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. */
|
/* POLLIN: Data other than high-priority data may be read without blocking. */
|
||||||
|
|
||||||
if ((fds->events & POLLIN) != 0)
|
if ((fds->events & POLLIN) != 0)
|
||||||
{
|
{
|
||||||
|
fds->priv = pollp->src;
|
||||||
ret = file_poll(&dev->pd_src, fds, setup);
|
ret = file_poll(&dev->pd_src, fds, setup);
|
||||||
}
|
if (ret < 0)
|
||||||
|
|
||||||
if (ret >= OK || ret == -ENOTTY)
|
|
||||||
{
|
|
||||||
/* POLLOUT: Normal data may be written without blocking. */
|
|
||||||
|
|
||||||
if ((fds->events & POLLOUT) != 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;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user