summaryrefslogtreecommitdiff
path: root/nuttx/drivers/pipe_common.c
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 20:24:28 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-11-17 20:24:28 +0000
commitcff1141190d60f819078be1ad0ed0186b47fd637 (patch)
tree487fc2ad11a4e20eb21f1ad746ed16d88541c05e /nuttx/drivers/pipe_common.c
parent33f0979adc4165594164fb13611961d60f0f2cfc (diff)
downloadpx4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.tar.gz
px4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.tar.bz2
px4-nuttx-cff1141190d60f819078be1ad0ed0186b47fd637.zip
Add poll() method
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1262 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/drivers/pipe_common.c')
-rw-r--r--nuttx/drivers/pipe_common.c137
1 files changed, 136 insertions, 1 deletions
diff --git a/nuttx/drivers/pipe_common.c b/nuttx/drivers/pipe_common.c
index 59b9f79c8..f00705f70 100644
--- a/nuttx/drivers/pipe_common.c
+++ b/nuttx/drivers/pipe_common.c
@@ -52,6 +52,8 @@
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
+#include <debug.h>
+
#include <nuttx/fs.h>
#include "pipe_common.h"
@@ -97,6 +99,33 @@ static void pipecommon_semtake(sem_t *sem)
}
/****************************************************************************
+ * Name: pipecommon_pollnotify
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+static void pipecommon_pollnotify(FAR struct pipe_dev_s *dev, pollevent_t eventset)
+{
+ int i;
+
+ for (i = 0; i < CONFIG_DEV_PIPE_NPOLLWAITERS; i++)
+ {
+ struct pollfd *fds = dev->d_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 pipecommon_pollnotify(dev,event)
+#endif
+
+/****************************************************************************
* Public Functions
****************************************************************************/
@@ -168,6 +197,10 @@ int pipecommon_open(FAR struct file *filep)
}
}
+ /* There is no, file-specific private data (at least not yet) */
+
+ filep->f_priv = NULL;
+
/* Increment the reference count on the pipe instance */
dev->d_refs++;
@@ -335,6 +368,7 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
sem_post(&dev->d_bfsem);
ret = sem_wait(&dev->d_rdsem);
sched_unlock();
+
if (ret < 0 || sem_wait(&dev->d_bfsem) < 0)
{
return ERROR;
@@ -361,8 +395,12 @@ ssize_t pipecommon_read(FAR struct file *filep, FAR char *buffer, size_t len)
sem_post(&dev->d_wrsem);
}
+ /* Notify all poll/select waiters that they can write to the FIFO */
+
+ pipecommon_pollnotify(dev, POLLOUT);
+
sem_post(&dev->d_bfsem);
- return nread;
+ return nread;
}
/****************************************************************************
@@ -426,6 +464,10 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t
sem_post(&dev->d_rdsem);
}
+ /* Notify all poll/select waiters that they can write to the FIFO */
+
+ pipecommon_pollnotify(dev, POLLIN);
+
/* Return the number of bytes written */
sem_post(&dev->d_bfsem);
@@ -470,4 +512,97 @@ ssize_t pipecommon_write(FAR struct file *filep, FAR const char *buffer, size_t
}
}
+/****************************************************************************
+ * Name: pipecommon_poll
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+int pipecommon_poll(FAR struct file *filep, FAR struct pollfd *fds)
+{
+ struct inode *inode = filep->f_inode;
+ struct pipe_dev_s *dev = inode->i_private;
+ pollevent_t eventset;
+ pipe_ndx_t nbytes;
+ int i;
+
+ /* Some sanity checking */
+#if CONFIG_DEBUG
+ if (!dev)
+ {
+ return -ENODEV;
+ }
+#endif
+
+ /* Find an available slot for the poll structure reference */
+
+ pipecommon_semtake(&dev->d_bfsem);
+ for (i = 0; i < CONFIG_DEV_PIPE_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->d_fds[i] == filep->f_priv)
+ {
+ dev->d_fds[i] = fds;
+ break;
+ }
+ }
+
+ if (i >= CONFIG_DEV_PIPE_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)
+ {
+ /* Determine how many bytes are in the buffer */
+
+ if (dev->d_wrndx >= dev->d_rdndx)
+ {
+ nbytes = dev->d_wrndx - dev->d_rdndx;
+ }
+ else
+ {
+ nbytes = (CONFIG_DEV_PIPE_SIZE-1) + dev->d_wrndx - dev->d_rdndx;
+ }
+
+ /* Notify the POLLOUT event if the pipe is not full */
+
+ eventset = 0;
+ if (nbytes < (CONFIG_DEV_PIPE_SIZE-1))
+ {
+ eventset |= POLLOUT;
+ }
+
+ /* Notify the POLLIN event if the pipe is not empty */
+
+ if (nbytes > 0)
+ {
+ eventset |= POLLIN;
+ }
+
+ if (eventset)
+ {
+ pipecommon_pollnotify(dev, eventset);
+ }
+ }
+
+ sem_post(&dev->d_bfsem);
+ return OK;
+}
+#endif
+
#endif /* CONFIG_DEV_PIPE_SIZE > 0 */