summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 23:22:27 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 23:22:27 +0000
commit09f70284f5e1d190519661166422909e69b2331b (patch)
treeb968095164f6f6417386d02feda27ea7e7d434ca
parent5c3162da749c8c8c1609c1ab1c85ab1961dbabde (diff)
downloadpx4-nuttx-09f70284f5e1d190519661166422909e69b2331b.tar.gz
px4-nuttx-09f70284f5e1d190519661166422909e69b2331b.tar.bz2
px4-nuttx-09f70284f5e1d190519661166422909e69b2331b.zip
Add poll method to serial drivers
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1268 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/Documentation/NuttX.html2
-rw-r--r--nuttx/arch/sim/src/up_devconsole.c14
-rw-r--r--nuttx/drivers/serial.c184
-rw-r--r--nuttx/drivers/serialirq.c41
-rw-r--r--nuttx/drivers/usbdev/usbdev_serial.c59
-rw-r--r--nuttx/examples/poll/poll_listener.c159
-rw-r--r--nuttx/include/nuttx/serial.h48
8 files changed, 401 insertions, 108 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 32760238a..f6e64259c 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -565,6 +565,6 @@
0.3.19 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Add poll() and select() APIs (in the initial check-in, these work only with character devices)
- * Add poll() methods to /dev/null, /dev/zero, pipes, and fifos.
+ * Add poll() methods to /dev/null, /dev/zero, pipes, fifos, and serial drivers.
* Add examples/poll for testing poll() and select()
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index e149f42a8..cf3e9603d 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -1201,7 +1201,7 @@ buildroot-0.1.2 2007-11-06 &lt;spudmonkey@racsa.co.cr&gt
<pre><ul>
nuttx-0.3.19 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Add poll() and select() APIs (in the initial check-in, these work only with character devices)
- * Add poll() methods to /dev/null, /dev/zero, pipes, and fifos.
+ * Add poll() methods to /dev/null, /dev/zero, pipes, fifos, and serial drivers.
* Add examples/poll for testing poll() and select()
pascal-0.1.3 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
diff --git a/nuttx/arch/sim/src/up_devconsole.c b/nuttx/arch/sim/src/up_devconsole.c
index 6bf733f71..58fa21e3b 100644
--- a/nuttx/arch/sim/src/up_devconsole.c
+++ b/nuttx/arch/sim/src/up_devconsole.c
@@ -53,6 +53,9 @@
static ssize_t devconsole_read(struct file *, char *, size_t);
static ssize_t devconsole_write(struct file *, const char *, size_t);
+#ifndef CONFIG_DISABLE_POLL
+static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds);
+#endif
/****************************************************************************
* Private Data
@@ -62,14 +65,16 @@ static struct file_operations devconsole_fops =
{
.read = devconsole_read,
.write = devconsole_write,
+#ifndef CONFIG_DISABLE_POLL
+ .poll = devconsole_poll,
+#endif
};
/****************************************************************************
* Private Functions
****************************************************************************/
-
- static ssize_t devconsole_read(struct file *filp, char *buffer, size_t len)
+static ssize_t devconsole_read(struct file *filp, char *buffer, size_t len)
{
return up_hostread(buffer, len);
}
@@ -79,6 +84,11 @@ static ssize_t devconsole_write(struct file *filp, const char *buffer, size_t le
return up_hostwrite(buffer, len);
}
+static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds)
+{
+ return OK;
+}
+
/****************************************************************************
* Public Functions
****************************************************************************/
diff --git a/nuttx/drivers/serial.c b/nuttx/drivers/serial.c
index 366c7a208..2939bf61f 100644
--- a/nuttx/drivers/serial.c
+++ b/nuttx/drivers/serial.c
@@ -44,6 +44,7 @@
#include <semaphore.h>
#include <string.h>
#include <fcntl.h>
+#include <poll.h>
#include <errno.h>
#include <debug.h>
@@ -77,6 +78,9 @@ static int uart_close(FAR struct file *filep);
static ssize_t uart_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
static ssize_t uart_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+#ifndef CONFIG_DISABLE_POLL
+static int uart_poll(FAR struct file *filep, FAR struct pollfd *fds);
+#endif
/************************************************************************************
* Private Variables
@@ -89,8 +93,10 @@ struct file_operations g_serialops =
uart_read, /* read */
uart_write, /* write */
0, /* seek */
- uart_ioctl, /* ioctl */
- 0 /* poll */
+ uart_ioctl /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+ , uart_poll /* poll */
+#endif
};
/************************************************************************************
@@ -119,6 +125,33 @@ static void uart_takesem(FAR sem_t *sem)
#define uart_givesem(sem) (void)sem_post(sem)
+/****************************************************************************
+ * Name: uart_pollnotify
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+static void uart_pollnotify(FAR uart_dev_t *dev, pollevent_t eventset)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++)
+ {
+ struct pollfd *fds = dev->fds[i];
+ if (fds)
+ {
+ fds->revents |= (fds->events & eventset);
+ if (fds->revents != 0)
+ {
+ fvdbg("Report events: %02x\n", fds->revents);
+ sem_post(fds->sem);
+ }
+ }
+ }
+}
+#else
+# define uart_pollnotify(dev,event)
+#endif
+
/************************************************************************************
* Name: uart_putxmitchar
************************************************************************************/
@@ -340,6 +373,98 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
return dev->ops->ioctl(filep, cmd, arg);
}
+/****************************************************************************
+ * Name: uart_poll
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+int uart_poll(FAR struct file *filep, FAR struct pollfd *fds)
+{
+ FAR struct inode *inode = filep->f_inode;
+ FAR uart_dev_t *dev = inode->i_private;
+ pollevent_t eventset;
+ int ndx;
+ int i;
+
+ /* Some sanity checking */
+#if CONFIG_DEBUG
+ if (!dev)
+ {
+ return -ENODEV;
+ }
+#endif
+
+ /* Find an available slot for the poll structure reference */
+
+ uart_takesem(&dev->pollsem);
+ for (i = 0; i < CONFIG_DEV_CONSOLE_NPOLLWAITERS; i++)
+ {
+ /* Find the slot with the value equal to filep->f_priv. If there
+ * is not previously installed poll structure, then f_priv will
+ * be NULL and we will find the first unused slot. If f_priv is
+ * is non-NULL, then we will find the slot that was used for the
+ * previous setup.
+ */
+
+ if (dev->fds[i] == filep->f_priv)
+ {
+ dev->fds[i] = fds;
+ break;
+ }
+ }
+
+ if (i >= CONFIG_DEV_CONSOLE_NPOLLWAITERS)
+ {
+ DEBUGASSERT(fds == NULL);
+ return -EBUSY;
+ }
+
+ /* Set or clear the poll event structure reference in the 'struct file'
+ * private data.
+ */
+
+ filep->f_priv = fds;
+
+ /* Check if we should immediately notify on any of the requested events */
+
+ if (fds)
+ {
+ /* Check if the xmit buffer is full. */
+
+ eventset = 0;
+
+ uart_takesem(&dev->xmit.sem);
+ ndx = dev->xmit.head + 1;
+ if (ndx >= dev->xmit.size)
+ {
+ ndx = 0;
+ }
+ if (ndx != dev->xmit.tail)
+ {
+ eventset |= POLLOUT;
+ }
+ uart_givesem(&dev->xmit.sem);
+
+ /* Check if the receive buffer is empty */
+
+ uart_takesem(&dev->recv.sem);
+ if (dev->recv.head != dev->recv.tail)
+ {
+ eventset |= POLLIN;
+ }
+ uart_givesem(&dev->recv.sem);
+
+ if (eventset)
+ {
+ uart_pollnotify(dev, eventset);
+ }
+ }
+
+ uart_givesem(&dev->pollsem);
+ return OK;
+}
+#endif
+
/************************************************************************************
* Name: uart_close
*
@@ -513,7 +638,62 @@ int uart_register(FAR const char *path, FAR uart_dev_t *dev)
sem_init(&dev->closesem, 0, 1);
sem_init(&dev->xmitsem, 0, 0);
sem_init(&dev->recvsem, 0, 0);
+#ifndef CONFIG_DISABLE_POLL
+ sem_init(&dev->pollsem, 0, 1);
+#endif
dbg("Registering %s\n", path);
return register_driver(path, &g_serialops, 0666, dev);
}
+
+/************************************************************************************
+ * Name: uart_datareceived
+ *
+ * Description:
+ * This function is called from uart_recvchars when new serial data is place in
+ * the driver's circular buffer. This function will wake-up any stalled read()
+ * operations that are waiting for incoming data.
+ *
+ ************************************************************************************/
+
+void uart_datareceived(FAR uart_dev_t *dev)
+{
+ /* Awaken any awaiting read() operations */
+
+ if (dev->recvwaiting)
+ {
+ dev->recvwaiting = FALSE;
+ (void)sem_post(&dev->recvsem);
+ }
+
+ /* Notify all poll/select waiters that they can read from the recv buffer */
+
+ uart_pollnotify(dev, POLLIN);
+
+}
+
+/************************************************************************************
+ * Name: uart_datasent
+ *
+ * Description:
+ * This function is called from uart_xmitchars after serial data has been sent,
+ * freeing up some space in the driver's circular buffer. This function will
+ * wake-up any stalled write() operations that was waiting for space to buffer
+ * outgoing data.
+ *
+ ************************************************************************************/
+
+void uart_datasent(FAR uart_dev_t *dev)
+{
+ if (dev->xmitwaiting)
+ {
+ dev->xmitwaiting = FALSE;
+ (void)sem_post(&dev->xmitsem);
+ }
+
+ /* Notify all poll/select waiters that they can write to xmit buffer */
+
+ uart_pollnotify(dev, POLLOUT);
+}
+
+
diff --git a/nuttx/drivers/serialirq.c b/nuttx/drivers/serialirq.c
index f7503e4cc..d1a18b257 100644
--- a/nuttx/drivers/serialirq.c
+++ b/nuttx/drivers/serialirq.c
@@ -80,6 +80,8 @@
void uart_xmitchars(FAR uart_dev_t *dev)
{
+ uint16 nbytes = 0;
+
/* Send while we still have data & room in the fifo */
while (dev->xmit.head != dev->xmit.tail && uart_txready(dev))
@@ -87,6 +89,7 @@ void uart_xmitchars(FAR uart_dev_t *dev)
/* Send the next byte */
uart_send(dev, dev->xmit.buffer[dev->xmit.tail]);
+ nbytes++;
/* Increment the tail index */
@@ -94,16 +97,6 @@ void uart_xmitchars(FAR uart_dev_t *dev)
{
dev->xmit.tail = 0;
}
-
- /* A byte was removed from the buffer. Inform any waiters
- * there there is space available.
- */
-
- if (dev->xmitwaiting)
- {
- dev->xmitwaiting = FALSE;
- (void)sem_post(&dev->xmitsem);
- }
}
/* When all of the characters have been sent from the buffer
@@ -114,6 +107,15 @@ void uart_xmitchars(FAR uart_dev_t *dev)
{
uart_disabletxint(dev);
}
+
+ /* If any bytes were removed from the buffer, inform any waiters
+ * there there is space available.
+ */
+
+ if (nbytes)
+ {
+ uart_datasent(dev);
+ }
}
/************************************************************************************
@@ -131,6 +133,7 @@ void uart_recvchars(FAR uart_dev_t *dev)
{
unsigned int status;
int nexthead = dev->recv.head + 1;
+ uint16 nbytes = 0;
if (nexthead >= dev->recv.size)
{
@@ -146,6 +149,7 @@ void uart_recvchars(FAR uart_dev_t *dev)
/* Add the character to the buffer */
dev->recv.buffer[dev->recv.head] = uart_receive(dev, &status);
+ nbytes++;
/* Increment the head index */
@@ -154,18 +158,15 @@ void uart_recvchars(FAR uart_dev_t *dev)
{
nexthead = 0;
}
+ }
- /* A character was added... if there is a thread waiting for more data, then
- * post the recvsem semaphore to wake it up. NOTE: There is a logic error in
- * the above looping logic: If nexthead == dev->recv.tail on entry and
- * recvwaiting is true, the recvsem will never get posted!
- */
+ /* If any bytes were added to the buffer, inform any waiters
+ * there there is new incoming data available.
+ */
- if (dev->recvwaiting)
- {
- dev->recvwaiting = FALSE;
- (void)sem_post(&dev->recvsem);
- }
+ if (nbytes)
+ {
+ uart_datareceived(dev);
}
}
diff --git a/nuttx/drivers/usbdev/usbdev_serial.c b/nuttx/drivers/usbdev/usbdev_serial.c
index 4b32ac052..116accc57 100644
--- a/nuttx/drivers/usbdev/usbdev_serial.c
+++ b/nuttx/drivers/usbdev/usbdev_serial.c
@@ -526,14 +526,6 @@ static uint16 usbclass_fillrequest(FAR struct usbser_dev_s *priv, char *reqbuf,
{
xmit->tail = 0;
}
-
- /* Check if we have to wake up the serial driver */
-
- if (serdev->xmitwaiting)
- {
- serdev->xmitwaiting = FALSE;
- sem_post(&serdev->xmitsem);
- }
}
/* When all of the characters have been sent from the buffer
@@ -545,6 +537,15 @@ static uint16 usbclass_fillrequest(FAR struct usbser_dev_s *priv, char *reqbuf,
uart_disabletxint(serdev);
}
+ /* If any bytes were removed from the buffer, inform any waiters
+ * there there is space available.
+ */
+
+ if (nbytes)
+ {
+ uart_datasent(serdev);
+ }
+
irqrestore(flags);
return nbytes;
}
@@ -651,6 +652,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv,
FAR struct uart_buffer_s *recv = &serdev->recv;
uint16 currhead;
uint16 nexthead;
+ uint16 nbytes = 0;
/* Get the next head index. During the time that RX interrupts are disabled, the
* the serial driver will be extracting data from the circular buffer and modifying
@@ -684,7 +686,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv,
* then we have overrun the serial driver and data will be lost.
*/
- while (nexthead != recv->tail && reqlen > 0)
+ while (nexthead != recv->tail && nbytes < reqlen)
{
/* Copy one byte to the head of the circular RX buffer */
@@ -693,21 +695,7 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv,
/* Update counts and indices */
currhead = nexthead;
- reqlen--;
-
- /* Wake up the serial driver if it is waiting for incoming data. If we
- * are running in an interrupt handler, then the serial driver will
- * not run until the interrupt handler returns. But we will exercise
- * care in the following just in case the serial driver does run.
- */
-
- if (priv->rxenabled && serdev->recvwaiting)
- {
- recv->head = currhead;
- serdev->recvwaiting = FALSE;
- sem_post(&serdev->recvsem);
- currhead = recv->head;
- }
+ nbytes++;
/* Increment the head index and check for wrap around */
@@ -731,9 +719,20 @@ static inline int usbclass_recvpacket(FAR struct usbser_dev_s *priv,
priv->rxhead = currhead;
}
+ /* If data was added to the incoming serial buffer, then wake up any
+ * threads is waiting for incoming data. If we are running in an interrupt
+ * handler, then the serial driver will not run until the interrupt handler
+ * returns.
+ */
+
+ if (priv->rxenabled && nbytes > 0)
+ {
+ uart_datareceived(serdev);
+ }
+
/* Return an error if the entire packet could not be transferred */
- if (reqlen > 0)
+ if (nbytes < reqlen)
{
usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_RXOVERRUN), 0);
return -ENOSPC;
@@ -2017,15 +2016,9 @@ static void usbser_rxint(FAR struct uart_dev_s *dev, boolean enable)
{
serdev->recv.head = priv->rxhead;
- /* Is the serial driver waiting for more data? */
+ /* Yes... signal the availability of new data */
- if (serdev->recvwaiting)
- {
- /* Yes... signal the availability of new data */
-
- sem_post(&serdev->recvsem);
- serdev->recvwaiting = FALSE;
- }
+ uart_datareceived(serdev);
}
/* RX "interrupts are no longer disabled */
diff --git a/nuttx/examples/poll/poll_listener.c b/nuttx/examples/poll/poll_listener.c
index 6182ca0de..c798b6e88 100644
--- a/nuttx/examples/poll/poll_listener.c
+++ b/nuttx/examples/poll/poll_listener.c
@@ -57,6 +57,17 @@
* Definitions
****************************************************************************/
+#if defined(CONFIG_DEV_CONSOLE) && !defined(CONFIG_DEV_LOWCONSOLE)
+# define HAVE_CONSOLE
+# define NPOLLFDS 2
+# define CONSNDX 0
+# define FIFONDX 1
+#else
+# undef HAVE_CONSOLE
+# define NPOLLFDS 1
+# define FIFONDX 0
+#endif
+
/****************************************************************************
* Private Types
****************************************************************************/
@@ -79,13 +90,15 @@
void *poll_listener(pthread_addr_t pvarg)
{
- struct pollfd fds;
+ struct pollfd fds[NPOLLFDS];
char buffer[64];
ssize_t nbytes;
boolean timeout;
boolean pollin;
+ int nevents;
int fd;
int ret;
+ int i;
/* Open the FIFO for non-blocking read */
@@ -105,15 +118,20 @@ void *poll_listener(pthread_addr_t pvarg)
{
message("poll_listener: Calling poll()\n");
- memset(&fds, 0, sizeof(struct pollfd));
- fds.fd = fd;
- fds.events = POLLIN;
- fds.revents = 0;
+ memset(fds, 0, sizeof(struct pollfd)*NPOLLFDS);
+#ifdef HAVE_CONSOLE
+ fds[CONSNDX].fd = 0;
+ fds[CONSNDX].events = POLLIN;
+ fds[CONSNDX].revents = 0;
+#endif
+ fds[FIFONDX].fd = fd;
+ fds[FIFONDX].events = POLLIN;
+ fds[FIFONDX].revents = 0;
- timeout = FALSE;
- pollin = FALSE;
+ timeout = FALSE;
+ pollin = FALSE;
- ret = poll(&fds, 1, POLL_LISTENER_DELAY);
+ ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY);
message("\npoll_listener: poll returned: %d\n", ret);
if (ret < 0)
@@ -122,71 +140,116 @@ void *poll_listener(pthread_addr_t pvarg)
}
else if (ret == 0)
{
- message("poll_listener: Timeout, revents=%02x\n", fds.revents);
+ message("poll_listener: Timeout\n");
timeout = TRUE;
- if (fds.revents != 0)
- {
- message("poll_listener: ERROR? expected revents=00, received revents=%02x\n",
- fds.revents);
- }
+ }
+ else if (ret > NPOLLFDS)
+ {
+ message("poll_listener: ERROR poll reported: %d\n");
}
else
{
- if (ret != 1)
+ pollin = TRUE;
+ }
+
+ nevents = 0;
+ for (i = 0; i < NPOLLFDS; i++)
+ {
+ message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents);
+ if (timeout)
{
- message("poll_listener: ERROR poll reported: %d\n");
+ if (fds[i].revents != 0)
+ {
+ message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n",
+ fds[i].revents, i);
+ }
}
- else
+ else if (pollin)
{
- pollin = TRUE;
+ if (fds[i].revents == POLLIN)
+ {
+ nevents++;
+ }
+ else if (fds[i].revents != 0)
+ {
+ message("poll_listener: ERROR unexpected revents[i]=%02x\n",
+ i, fds[i].revents);
+ }
}
+ }
- message("poll_listener: revents=%02x\n", fds.revents);
- if (fds.revents != POLLIN)
- {
- message("poll_listener: ERROR expected revents=%02x, received revents=%02x\n",
- fds.revents);
- message(" (might just be a race condition)\n");
- }
+ if (pollin && nevents != ret)
+ {
+ message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret);
}
- /* In any event, read until the pipe is empty */
+ /* In any event, read until the pipe/serial is empty */
- do
+ for (i = 0; i < NPOLLFDS; i++)
{
- nbytes = read(fd, buffer, 63);
- if (nbytes <= 0)
+ do
{
- if (nbytes == 0 || errno == EAGAIN)
+#ifdef HAVE_CONSOLE
+ /* Hack to work around the fact that the console driver on the
+ * simulator is always non-blocking.
+ */
+
+ if (i == CONSNDX)
{
- if (pollin)
+ if ((fds[CONSNDX].revents & POLLIN) != 0)
+ {
+ buffer[0] = getchar();
+ nbytes = 1;
+ }
+ else
{
- message("poll_listener: ERROR no read data\n");
+ nbytes = 0;
}
}
- else if (errno != EINTR)
+ else
+#endif
{
- message("poll_listener: read failed: %d\n", errno);
+ /* The pipe works differently, it returns whatever data
+ * it has available without blocking.
+ */
+
+ nbytes = read(fds[i].fd, buffer, 63);
}
- nbytes = 0;
- }
- else
- {
- if (timeout)
+
+ if (nbytes <= 0)
{
- message("poll_listener: ERROR? Poll timeout, but data read\n");
- message(" (might just be a race condition)\n");
+ if (nbytes == 0 || errno == EAGAIN)
+ {
+ if ((fds[i].revents & POLLIN) != 0)
+ {
+ message("poll_listener: ERROR no read data[%d]\n", i);
+ }
+ }
+ else if (errno != EINTR)
+ {
+ message("poll_listener: read[%d] failed: %d\n", i, errno);
+ }
+ nbytes = 0;
}
+ else
+ {
+ if (timeout)
+ {
+ message("poll_listener: ERROR? Poll timeout, but data read[%d]\n", i);
+ message(" (might just be a race condition)\n");
+ }
- buffer[nbytes] = '\0';
- message("poll_listener: Read '%s' (%d bytes)\n", buffer, nbytes);
- }
+ buffer[nbytes] = '\0';
+ message("poll_listener: Read[%d] '%s' (%d bytes)\n", i, buffer, nbytes);
+ }
- timeout = FALSE;
- pollin = FALSE;
- }
- while (nbytes > 0);
+ /* Suppress error report if no read data on the next time through */
+ fds[i].revents = 0;
+ }
+ while (nbytes > 0);
+ }
+
/* Make sure that everything is displayed */
msgflush();
diff --git a/nuttx/include/nuttx/serial.h b/nuttx/include/nuttx/serial.h
index 9954c16c0..ed5c6a1c0 100644
--- a/nuttx/include/nuttx/serial.h
+++ b/nuttx/include/nuttx/serial.h
@@ -49,6 +49,14 @@
* Definitions
************************************************************************************/
+/* Maximum number of threads than can be waiting for POLL events */
+
+#ifndef CONFIG_DEV_CONSOLE_NPOLLWAITERS
+# define CONFIG_DEV_CONSOLE_NPOLLWAITERS 2
+#endif
+
+/* vtable access helpers */
+
#define uart_setup(dev) dev->ops->setup(dev)
#define uart_shutdown(dev) dev->ops->shutdown(dev)
#define uart_attach(dev) dev->ops->attach(dev)
@@ -186,10 +194,23 @@ struct uart_dev_s
sem_t closesem; /* Locks out new open while close is in progress */
sem_t xmitsem; /* Wakeup user waiting for space in xmit.buffer */
sem_t recvsem; /* Wakeup user waiting for data in recv.buffer */
+#ifndef CONFIG_DISABLE_POLL
+ sem_t pollsem; /* Manages exclusive access to fds[] */
+#endif
struct uart_buffer_s xmit; /* Describes transmit buffer */
struct uart_buffer_s recv; /* Describes receive buffer */
FAR const struct uart_ops_s *ops; /* Arch-specific operations */
- FAR void *priv; /* Used by the arch-specific logic */
+ FAR void *priv; /* Used by the arch-specific logic */
+
+ /* The following is a list if poll structures of threads waiting for
+ * driver events. The 'struct pollfd' reference for each open is also
+ * retained in the f_priv field of the 'struct file'.
+ */
+
+#ifndef CONFIG_DISABLE_POLL
+ struct pollfd *fds[CONFIG_DEV_CONSOLE_NPOLLWAITERS];
+#endif
+
};
typedef struct uart_dev_s uart_dev_t;
@@ -245,6 +266,31 @@ EXTERN void uart_xmitchars(FAR uart_dev_t *dev);
EXTERN void uart_recvchars(FAR uart_dev_t *dev);
+/************************************************************************************
+ * Name: uart_datareceived
+ *
+ * Description:
+ * This function is called from uart_recvchars when new serial data is place in
+ * the driver's circular buffer. This function will wake-up any stalled read()
+ * operations that are waiting for incoming data.
+ *
+ ************************************************************************************/
+
+EXTERN void uart_datareceived(FAR uart_dev_t *dev);
+
+/************************************************************************************
+ * Name: uart_datasent
+ *
+ * Description:
+ * This function is called from uart_xmitchars after serial data has been sent,
+ * freeing up some space in the driver's circular buffer. This function will
+ * wake-up any stalled write() operations that was waiting for space to buffer
+ * outgoing data.
+ *
+ ************************************************************************************/
+
+EXTERN void uart_datasent(FAR uart_dev_t *dev);
+
#undef EXTERN
#if defined(__cplusplus)
}