summaryrefslogtreecommitdiff
path: root/apps/examples/poll
diff options
context:
space:
mode:
Diffstat (limited to 'apps/examples/poll')
-rw-r--r--apps/examples/poll/Makefile90
-rw-r--r--apps/examples/poll/Makefile.host54
-rw-r--r--apps/examples/poll/host.c166
-rw-r--r--apps/examples/poll/net_listener.c428
-rw-r--r--apps/examples/poll/net_reader.c317
-rw-r--r--apps/examples/poll/poll_internal.h128
-rw-r--r--apps/examples/poll/poll_listener.c262
-rw-r--r--apps/examples/poll/poll_main.c229
-rw-r--r--apps/examples/poll/select_listener.c193
9 files changed, 1867 insertions, 0 deletions
diff --git a/apps/examples/poll/Makefile b/apps/examples/poll/Makefile
new file mode 100644
index 000000000..0bfc97ec1
--- /dev/null
+++ b/apps/examples/poll/Makefile
@@ -0,0 +1,90 @@
+############################################################################
+# apps/examples/poll/Makefile
+#
+# Copyright (C) 2008, 2010-2011 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+-include $(TOPDIR)/.config
+-include $(TOPDIR)/Make.defs
+include $(APPDIR)/Make.defs
+
+# Device Driver poll()/select() Example
+
+ASRCS =
+CSRCS = poll_main.c poll_listener.c select_listener.c net_listener.c net_reader.c
+
+AOBJS = $(ASRCS:.S=$(OBJEXT))
+COBJS = $(CSRCS:.c=$(OBJEXT))
+
+SRCS = $(ASRCS) $(CSRCS)
+OBJS = $(AOBJS) $(COBJS)
+
+BIN = ../../libapps$(LIBEXT)
+
+ROOTDEPPATH = --dep-path .
+
+# Common build
+
+VPATH =
+
+all: .built
+.PHONY: .built clean depend disclean
+
+$(AOBJS): %$(OBJEXT): %.S
+ $(call ASSEMBLE, $<, $@)
+
+$(COBJS): %$(OBJEXT): %.c
+ $(call COMPILE, $<, $@)
+
+$(BIN): $(OBJS)
+ @( for obj in $(OBJS) ; do \
+ $(call ARCHIVE, $@, $${obj}); \
+ done ; )
+ @touch .built
+
+.built: $(BIN)
+
+.depend: Makefile $(SRCS)
+ @$(MKDEP) $(ROOTDEPPATH) $(CC) -- $(CFLAGS) -- $(SRCS) >Make.dep
+ @touch $@
+
+# Register application
+depend: .depend
+
+clean:
+ @rm -f $(BIN) *.o *~ .*.swp .built
+ $(call CLEAN)
+
+distclean: clean
+ @rm -f Make.dep .depend host
+
+-include Make.dep
diff --git a/apps/examples/poll/Makefile.host b/apps/examples/poll/Makefile.host
new file mode 100644
index 000000000..9d9daee27
--- /dev/null
+++ b/apps/examples/poll/Makefile.host
@@ -0,0 +1,54 @@
+############################################################################
+# apps/examples/poll/Makefile.host
+#
+# Copyright (C) 2008, 2009, 2011 Gregory Nutt. All rights reserved.
+# Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+############################################################################
+
+# TOPDIR must be defined on the make command line
+
+include $(TOPDIR)/.config
+include $(TOPDIR)/Make.defs
+
+SRC = host.c
+BIN = host
+
+DEFINES = -DTARGETIP=\"$(TARGETIP)\"
+
+all: $(BIN)
+
+$(BIN): $(SRC)
+ $(HOSTCC) $(HOSTCFLAGS) $(DEFINES) $^ -o $@
+
+clean:
+ @rm -f $(BIN) *~ .*.swp *.o
+ $(call CLEAN)
+
diff --git a/apps/examples/poll/host.c b/apps/examples/poll/host.c
new file mode 100644
index 000000000..47f2c3e53
--- /dev/null
+++ b/apps/examples/poll/host.c
@@ -0,0 +1,166 @@
+/****************************************************************************
+ * examples/poll/host.c
+ *
+ * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define pthread_addr_t void *
+#include "poll_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifndef TARGETIP
+# error TARGETIP not defined
+#endif
+
+#define IOBUFFER_SIZE 80
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * main
+ ****************************************************************************/
+
+int main(int argc, char **argv, char **envp)
+{
+ struct sockaddr_in myaddr;
+ char outbuf[IOBUFFER_SIZE];
+ char inbuf[IOBUFFER_SIZE];
+ int sockfd;
+ int len;
+ int nbytessent;
+ int nbytesrecvd;
+ int i;
+
+ /* Create a new TCP socket */
+
+ sockfd = socket(PF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+ message("client socket failure %d\n", errno);
+ goto errout_with_outbufs;
+ }
+
+ /* Connect the socket to the server */
+
+ myaddr.sin_family = AF_INET;
+ myaddr.sin_port = htons(LISTENER_PORT);
+ myaddr.sin_addr.s_addr = inet_addr(TARGETIP);
+
+ message("client: Connecting to %s...\n", TARGETIP);
+ if (connect( sockfd, (struct sockaddr*)&myaddr, sizeof(struct sockaddr_in)) < 0)
+ {
+ message("client: connect failure: %d\n", errno);
+ goto errout_with_socket;
+ }
+ message("client: Connected\n");
+
+ /* Then send and receive messages */
+
+ for (i = 0; ; i++)
+ {
+ sprintf(outbuf, "Remote message %d", i);
+ len = strlen(outbuf);
+
+ message("client: Sending '%s' (%d bytes)\n", outbuf, len);
+ nbytessent = send(sockfd, outbuf, len, 0);
+ message("client: Sent %d bytes\n", nbytessent);
+
+ if (nbytessent < 0)
+ {
+ message("client: send failed: %d\n", errno);
+ goto errout_with_socket;
+ }
+ else if (nbytessent != len)
+ {
+ message("client: Bad send length: %d Expected: %d\n", nbytessent, len);
+ goto errout_with_socket;
+ }
+
+ message("client: Receiving...\n");
+ nbytesrecvd = recv(sockfd, inbuf, IOBUFFER_SIZE, 0);
+
+ if (nbytesrecvd < 0)
+ {
+ message("client: recv failed: %d\n", errno);
+ goto errout_with_socket;
+ }
+
+ inbuf[nbytesrecvd] = '\0';
+ message("client: Received '%s' (%d bytes)\n", inbuf, nbytesrecvd);
+
+ if (nbytesrecvd != len)
+ {
+ message("client: Bad recv length: %d Expected: %d\n", nbytesrecvd, len);
+ goto errout_with_socket;
+ }
+ else if (memcmp(inbuf, outbuf, len) != 0)
+ {
+ message("client: Received outbuf does not match sent outbuf\n");
+ goto errout_with_socket;
+ }
+
+ message("client: Sleeping\n");
+ sleep(8);
+ }
+
+ close(sockfd);
+ return 0;
+
+errout_with_socket:
+ close(sockfd);
+errout_with_outbufs:
+ exit(1);
+}
diff --git a/apps/examples/poll/net_listener.c b/apps/examples/poll/net_listener.c
new file mode 100644
index 000000000..4d425c608
--- /dev/null
+++ b/apps/examples/poll/net_listener.c
@@ -0,0 +1,428 @@
+/****************************************************************************
+ * examples/poll/net_listener.c
+ *
+ * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <net/if.h>
+#include <apps/netutils/uiplib.h>
+
+#include "poll_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define IOBUFFER_SIZE 80
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct net_listener_s
+{
+ struct sockaddr_in addr;
+ fd_set master;
+ fd_set working;
+ char buffer[IOBUFFER_SIZE];
+ int listensd;
+ int mxsd;
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: net_closeclient
+ ****************************************************************************/
+
+static bool net_closeclient(struct net_listener_s *nls, int sd)
+{
+ message("net_listener: Closing host side connection sd=%d\n", sd);
+ close(sd);
+ FD_CLR(sd, &nls->master);
+
+ /* If we just closed the max SD, then search downward for the next biggest SD. */
+
+ while (FD_ISSET(nls->mxsd, &nls->master) == false)
+ {
+ nls->mxsd -= 1;
+ }
+ return true;
+}
+
+/****************************************************************************
+ * Name: net_incomingdata
+ ****************************************************************************/
+
+static inline bool net_incomingdata(struct net_listener_s *nls, int sd)
+{
+ char *ptr;
+ int nbytes;
+ int ret;
+
+ /* Read data from the socket */
+
+#ifdef FIONBIO
+ for (;;)
+#endif
+ {
+ message("net_listener: Read data from sd=%d\n", sd);
+ ret = recv(sd, nls->buffer, IOBUFFER_SIZE, 0);
+ if (ret < 0)
+ {
+ if (errno != EINTR)
+ {
+ message("net_listener: recv failed sd=%d: %d\n", sd, errno);
+ if (errno != EAGAIN)
+ {
+ net_closeclient(nls, sd);
+ return false;
+ }
+ }
+ }
+ else if (ret == 0)
+ {
+ message("net_listener: Client connection lost sd=%d\n", sd);
+ net_closeclient(nls, sd);
+ return false;
+ }
+ else
+ {
+ nls->buffer[ret]='\0';
+ message("poll_listener: Read '%s' (%d bytes)\n", nls->buffer, ret);
+
+ /* Echo the data back to the client */
+
+ for (nbytes = ret, ptr = nls->buffer; nbytes > 0; )
+ {
+ ret = send(sd, ptr, nbytes, 0);
+ if (ret < 0)
+ {
+ if (errno != EINTR)
+ {
+ message("net_listener: Send failed sd=%d: \n", sd, errno);
+ net_closeclient(nls, sd);
+ return false;
+ }
+ }
+ else
+ {
+ nbytes -= ret;
+ ptr += ret;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/****************************************************************************
+ * Name: net_connection
+ ****************************************************************************/
+
+static inline bool net_connection(struct net_listener_s *nls)
+{
+ int sd;
+
+ /* Loop until all connections have been processed */
+
+#ifdef FIONBIO
+ for (;;)
+#endif
+ {
+ message("net_listener: Accepting new connection on sd=%d\n", nls->listensd);
+
+ sd = accept(nls->listensd, NULL, NULL);
+ if (sd < 0)
+ {
+ message("net_listener: accept failed: %d\n", errno);
+
+ if (errno != EINTR)
+ {
+ return false;
+ }
+ }
+ else
+ {
+ /* Add the new connection to the master set */
+
+ message("net_listener: Connection accepted for sd=%d\n", sd);
+
+ FD_SET(sd, &nls->master);
+ if (sd > nls->mxsd)
+ {
+ nls->mxsd = sd;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+/****************************************************************************
+ * Name: net_mksocket
+ ****************************************************************************/
+
+static inline bool net_mksocket(struct net_listener_s *nls)
+{
+ int value;
+ int ret;
+
+ /* Create a listening socket */
+
+ message("net_listener: Initializing listener socket\n");
+ nls->listensd = socket(AF_INET, SOCK_STREAM, 0);
+ if (nls->listensd < 0)
+ {
+ message("net_listener: socket failed: %d\n", errno);
+ return false;
+ }
+
+ /* Configure the socket */
+
+ value = 1;
+ ret = setsockopt(nls->listensd, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(int));
+ if (ret < 0)
+ {
+ message("net_listener: setsockopt failed: %d\n", errno);
+ close(nls->listensd);
+ return false;
+ }
+
+ /* Set the socket to non-blocking */
+
+#ifdef FIONBIO
+ ret = ioctl(nls->listensd, FIONBIO, (char *)&value);
+ if (ret < 0)
+ {
+ message("net_listener: ioctl failed: %d\n", errno);
+ close(nls->listensd);
+ return false;
+ }
+#endif
+
+ /* Bind the socket */
+
+ memset(&nls->addr, 0, sizeof(struct sockaddr_in));
+ nls->addr.sin_family = AF_INET;
+ nls->addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ nls->addr.sin_port = htons(LISTENER_PORT);
+ ret = bind(nls->listensd, (struct sockaddr *)&nls->addr, sizeof(struct sockaddr_in));
+ if (ret < 0)
+ {
+ message("net_listener: bind failed: %d\n", errno);
+ close(nls->listensd);
+ return false;
+ }
+
+ /* Mark the socket as a listener */
+
+ ret = listen(nls->listensd, 32);
+ if (ret < 0)
+ {
+ message("net_listener: bind failed: %d\n", errno);
+ close(nls->listensd);
+ return false;
+ }
+
+ return true;
+}
+
+/****************************************************************************
+ * Name: net_configure
+ ****************************************************************************/
+
+static void net_configure(void)
+{
+ struct in_addr addr;
+#if defined(CONFIG_EXAMPLE_POLL_NOMAC)
+ uint8_t mac[IFHWADDRLEN];
+#endif
+
+ /* Configure uIP */
+ /* Many embedded network interfaces must have a software assigned MAC */
+
+#ifdef CONFIG_EXAMPLE_POLL_NOMAC
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0xb0;
+ mac[3] = 0x0b;
+ mac[4] = 0xba;
+ mac[5] = 0xbe;
+ uip_setmacaddr("eth0", mac);
+#endif
+
+ /* Set up our host address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR);
+ uip_sethostaddr("eth0", &addr);
+
+ /* Set up the default router address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR);
+ uip_setdraddr("eth0", &addr);
+
+ /* Setup the subnet mask */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK);
+ uip_setnetmask("eth0", &addr);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: net_listener
+ ****************************************************************************/
+
+void *net_listener(pthread_addr_t pvarg)
+{
+ struct net_listener_s nls;
+ struct timeval timeout;
+ int nsds;
+ int ret;
+ int i;
+
+ /* Configure uIP */
+
+ net_configure();
+
+ /* Set up a listening socket */
+
+ memset(&nls, 0, sizeof(struct net_listener_s));
+ if (!net_mksocket(&nls))
+ {
+ return (void*)1;
+ }
+
+ /* Initialize the 'master' file descriptor set */
+
+ FD_ZERO(&nls.master);
+ nls.mxsd = nls.listensd;
+ FD_SET(nls.listensd, &nls.master);
+
+ /* Set up a 3 second timeout */
+
+ timeout.tv_sec = NET_LISTENER_DELAY;
+ timeout.tv_usec = 0;
+
+ /* Loop waiting for incoming connections or for incoming data
+ * on any of the connect sockets.
+ */
+
+ for (;;)
+ {
+ /* Wait on select */
+
+ message("net_listener: Calling select(), listener sd=%d\n", nls.listensd);
+ memcpy(&nls.working, &nls.master, sizeof(fd_set));
+ ret = select(nls.mxsd + 1, (FAR fd_set*)&nls.working, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout);
+ if (ret < 0)
+ {
+ message("net_listener: select failed: %d\n", errno);
+ break;
+ }
+
+ /* Check for timeout */
+
+ if (ret == 0)
+ {
+ message("net_listener: Timeout\n");
+ continue;
+ }
+
+ /* Find which descriptors caused the wakeup */
+
+ nsds = ret;
+ for (i = 0; i <= nls.mxsd && nsds > 0; i++)
+ {
+ /* Is this descriptor ready? */
+
+ if (FD_ISSET(i, &nls.working))
+ {
+ /* Yes, is it our listener? */
+
+ message("net_listener: Activity on sd=%d\n", i);
+
+ nsds--;
+ if (i == nls.listensd)
+ {
+ (void)net_connection(&nls);
+ }
+ else
+ {
+ net_incomingdata(&nls, i);
+ }
+ }
+ }
+ }
+
+ /* Cleanup */
+
+#if 0 /* Don't get here */
+ for (i = 0; i <= nls.mxsd; +i++)
+ {
+ if (FD_ISSET(i, &nls.master))
+ {
+ close(i);
+ }
+ }
+#endif
+ return NULL; /* Keeps some compilers from complaining */
+}
diff --git a/apps/examples/poll/net_reader.c b/apps/examples/poll/net_reader.c
new file mode 100644
index 000000000..b0cf94316
--- /dev/null
+++ b/apps/examples/poll/net_reader.c
@@ -0,0 +1,317 @@
+/****************************************************************************
+ * examples/poll/net_reader.c
+ *
+ * Copyright (C) 2008-2009, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <net/if.h>
+#include <apps/netutils/uiplib.h>
+
+#include "poll_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#define IOBUFFER_SIZE 80
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: net_configure
+ ****************************************************************************/
+
+static void net_configure(void)
+{
+ struct in_addr addr;
+#if defined(CONFIG_EXAMPLE_POLL_NOMAC)
+ uint8_t mac[IFHWADDRLEN];
+#endif
+
+ /* Configure uIP */
+ /* Many embedded network interfaces must have a software assigned MAC */
+
+#ifdef CONFIG_EXAMPLE_POLL_NOMAC
+ mac[0] = 0x00;
+ mac[1] = 0xe0;
+ mac[2] = 0xb0;
+ mac[3] = 0x0b;
+ mac[4] = 0xba;
+ mac[5] = 0xbe;
+ uip_setmacaddr("eth0", mac);
+#endif
+
+ /* Set up our host address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_IPADDR);
+ uip_sethostaddr("eth0", &addr);
+
+ /* Set up the default router address */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_DRIPADDR);
+ uip_setdraddr("eth0", &addr);
+
+ /* Setup the subnet mask */
+
+ addr.s_addr = HTONL(CONFIG_EXAMPLE_POLL_NETMASK);
+ uip_setnetmask("eth0", &addr);
+}
+
+/****************************************************************************
+ * Name: net_receive
+ ****************************************************************************/
+
+static void net_receive(int sd)
+{
+ struct timeval timeout;
+ char buffer[IOBUFFER_SIZE];
+ char *ptr;
+ fd_set readset;
+ int nbytes;
+ int ret;
+
+ /* Set up the timeout */
+
+ timeout.tv_sec = NET_LISTENER_DELAY;
+ timeout.tv_usec = 0;
+
+ /* Loop while we have the connection */
+
+ for (;;)
+ {
+ /* Wait for incoming message */
+
+ do
+ {
+ FD_ZERO(&readset);
+ FD_SET(sd, &readset);
+ ret = select(sd + 1, (FAR fd_set*)&readset, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &timeout);
+ }
+ while (ret < 0 && errno == EINTR);
+
+ /* Something has happened */
+
+ if (ret < 0)
+ {
+ message("net_reader: select failed: %d\n", errno);
+ return;
+ }
+ else if (ret == 0)
+ {
+ message("net_reader: Timeout\n");
+ }
+ else
+ {
+ message("net_reader: Read data from sd=%d\n", sd);
+ memset(buffer, '?', IOBUFFER_SIZE); /* Just to make sure we really receive something */
+ ret = recv(sd, buffer, IOBUFFER_SIZE, 0);
+ if (ret < 0)
+ {
+ if (errno != EINTR)
+ {
+ message("net_reader: recv failed sd=%d: %d\n", sd, errno);
+ if (errno != EAGAIN)
+ {
+ return;
+ }
+ }
+ }
+ else if (ret == 0)
+ {
+ message("net_reader: Client connection lost sd=%d\n", sd);
+ return;
+ }
+ else
+ {
+ buffer[ret]='\0';
+ message("net_reader: Read '%s' (%d bytes)\n", buffer, ret);
+
+ /* Echo the data back to the client */
+
+ for (nbytes = ret, ptr = buffer; nbytes > 0; )
+ {
+ ret = send(sd, ptr, nbytes, 0);
+ if (ret < 0)
+ {
+ if (errno != EINTR)
+ {
+ message("net_reader: Send failed sd=%d: %d\n", sd, errno);
+ return;
+ }
+ }
+ else
+ {
+ nbytes -= ret;
+ ptr += ret;
+ }
+ }
+ }
+ }
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: net_reader
+ ****************************************************************************/
+
+void *net_reader(pthread_addr_t pvarg)
+{
+ struct sockaddr_in addr;
+#ifdef POLL_HAVE_SOLINGER
+ struct linger ling;
+#endif
+ int listensd;
+ int acceptsd;
+ socklen_t addrlen;
+ int optval;
+
+ /* Configure uIP */
+
+ net_configure();
+
+ /* Create a new TCP socket */
+
+ listensd = socket(PF_INET, SOCK_STREAM, 0);
+ if (listensd < 0)
+ {
+ message("net_reader: socket failure: %d\n", errno);
+ goto errout;
+ }
+
+ /* Set socket to reuse address */
+
+ optval = 1;
+ if (setsockopt(listensd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(int)) < 0)
+ {
+ message("net_reader: setsockopt SO_REUSEADDR failure: %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ /* Bind the socket to a local address */
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = HTONS(LISTENER_PORT);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(listensd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
+ {
+ message("net_reader: bind failure: %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ /* Listen for connections on the bound TCP socket */
+
+ if (listen(listensd, 5) < 0)
+ {
+ message("net_reader: listen failure %d\n", errno);
+ goto errout_with_listensd;
+ }
+
+ /* Connection loop */
+
+ for (;;)
+ {
+ /* Accept only one connection */
+
+ message("net_reader: Accepting new connections on port %d\n", LISTENER_PORT);
+ addrlen = sizeof(struct sockaddr_in);
+ acceptsd = accept(listensd, (struct sockaddr*)&addr, &addrlen);
+ if (acceptsd < 0)
+ {
+ message("net_reader: accept failure: %d\n", errno);
+ continue;
+ }
+ message("net_reader: Connection accepted on sd=%d\n", acceptsd);
+
+ /* Configure to "linger" until all data is sent when the socket is closed */
+
+#ifdef POLL_HAVE_SOLINGER
+ ling.l_onoff = 1;
+ ling.l_linger = 30; /* timeout is seconds */
+ if (setsockopt(acceptsd, SOL_SOCKET, SO_LINGER, &ling, sizeof(struct linger)) < 0)
+ {
+ message("net_reader: setsockopt SO_LINGER failure: %d\n", errno);
+ goto errout_with_acceptsd;
+ }
+#endif
+
+ /* Handle incoming messsages on the connection. */
+
+ net_receive(acceptsd);
+
+ message("net_reader: Closing sd=%d\n", acceptsd);
+ close(acceptsd);
+ }
+
+#ifdef POLL_HAVE_SOLINGER
+errout_with_acceptsd:
+ close(acceptsd);
+#endif
+errout_with_listensd:
+ close(listensd);
+errout:
+ return NULL;
+}
diff --git a/apps/examples/poll/poll_internal.h b/apps/examples/poll/poll_internal.h
new file mode 100644
index 000000000..cbf42ac56
--- /dev/null
+++ b/apps/examples/poll/poll_internal.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+ * examples/poll/poll_internal.h
+ *
+ * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __EXAMPLES_PIPE_PIPE_H
+#define __EXAMPLES_PIPE_PIPE_H
+
+/****************************************************************************
+ * Compilation Switches
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <pthread.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_DISABLE_POLL
+# error "The polling API is disabled"
+#endif
+
+/* Here are all of the configuration settings that must be met to have TCP/IP
+ * poll/select support. This kind of looks like overkill.
+ *
+ * CONFIG_NET - Network support must be enabled
+ * CONFIG_NSOCKET_DESCRIPTORS - Socket descriptors must be allocated
+ * CONFIG_NET_TCP - Only support on TCP (because read-ahead
+ * ibuffering s not yet support for UDP)
+ * CONFIG_NET_NTCP_READAHEAD_BUFFERS - TCP/IP read-ahead buffering must be enabled
+ */
+
+#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && \
+ defined(CONFIG_NET_TCP) && CONFIG_NET_NTCP_READAHEAD_BUFFERS > 0
+# define HAVE_NETPOLL 1
+#else
+# undef HAVE_NETPOLL
+#endif
+
+/* If debug is enabled, then use lib_rawprintf so that OS debug output and
+ * the test output are synchronized.
+ *
+ * These macros will differ depending upon if the toolchain supports
+ * macros with a variable number of arguments or not.
+ */
+
+#ifdef CONFIG_CPP_HAVE_VARARGS
+# ifdef CONFIG_DEBUG
+# define message(...) lib_rawprintf(__VA_ARGS__)
+# define msgflush()
+# else
+# define message(...) printf(__VA_ARGS__)
+# define msgflush() fflush(stdout)
+# endif
+#else
+# ifdef CONFIG_DEBUG
+# define message lib_rawprintf
+# define msgflush()
+# else
+# define message printf
+# define msgflush() fflush(stdout)
+# endif
+#endif
+
+#define FIFO_PATH1 "/dev/fifo0"
+#define FIFO_PATH2 "/dev/fifo1"
+
+#define POLL_LISTENER_DELAY 2000 /* 2 seconds */
+#define SELECT_LISTENER_DELAY 4 /* 4 seconds */
+#define NET_LISTENER_DELAY 3 /* 3 seconds */
+#define WRITER_DELAY 6 /* 6 seconds */
+
+#define LISTENER_PORT 5471
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+extern void *poll_listener(pthread_addr_t pvarg);
+extern void *select_listener(pthread_addr_t pvarg);
+
+#ifdef HAVE_NETPOLL
+extern void *net_listener(pthread_addr_t pvarg);
+extern void *net_reader(pthread_addr_t pvarg);
+#endif
+#endif /* __EXAMPLES_PIPE_PIPE_H */
diff --git a/apps/examples/poll/poll_listener.c b/apps/examples/poll/poll_listener.c
new file mode 100644
index 000000000..816647e34
--- /dev/null
+++ b/apps/examples/poll/poll_listener.c
@@ -0,0 +1,262 @@
+/****************************************************************************
+ * examples/poll/poll_listener.c
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "poll_internal.h"
+
+/****************************************************************************
+ * 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
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: poll_listener
+ ****************************************************************************/
+
+void *poll_listener(pthread_addr_t pvarg)
+{
+ struct pollfd fds[NPOLLFDS];
+ char buffer[64];
+ ssize_t nbytes;
+ bool timeout;
+ bool pollin;
+ int nevents;
+ int fd;
+ int ret;
+ int i;
+
+ /* Open the FIFO for non-blocking read */
+
+ message("poll_listener: Opening %s for non-blocking read\n", FIFO_PATH1);
+ fd = open(FIFO_PATH1, O_RDONLY|O_NONBLOCK);
+ if (fd < 0)
+ {
+ message("poll_listener: ERROR Failed to open FIFO %s: %d\n",
+ FIFO_PATH1, errno);
+ (void)close(fd);
+ return (void*)-1;
+ }
+
+ /* Loop forever */
+
+ for (;;)
+ {
+ message("poll_listener: Calling poll()\n");
+
+ 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;
+
+ ret = poll(fds, NPOLLFDS, POLL_LISTENER_DELAY);
+
+ message("\npoll_listener: poll returned: %d\n", ret);
+ if (ret < 0)
+ {
+ message("poll_listener: ERROR poll failed: %d\n", errno);
+ }
+ else if (ret == 0)
+ {
+ message("poll_listener: Timeout\n");
+ timeout = true;
+ }
+ else if (ret > NPOLLFDS)
+ {
+ message("poll_listener: ERROR poll reported: %d\n");
+ }
+ else
+ {
+ pollin = true;
+ }
+
+ nevents = 0;
+ for (i = 0; i < NPOLLFDS; i++)
+ {
+ message("poll_listener: FIFO revents[%d]=%02x\n", i, fds[i].revents);
+ if (timeout)
+ {
+ if (fds[i].revents != 0)
+ {
+ message("poll_listener: ERROR? expected revents=00, received revents[%d]=%02x\n",
+ fds[i].revents, i);
+ }
+ }
+ else if (pollin)
+ {
+ 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);
+ }
+ }
+ }
+
+ if (pollin && nevents != ret)
+ {
+ message("poll_listener: ERROR found %d events, poll reported %d\n", nevents, ret);
+ }
+
+ /* In any event, read until the pipe/serial is empty */
+
+ for (i = 0; i < NPOLLFDS; i++)
+ {
+ do
+ {
+#ifdef HAVE_CONSOLE
+ /* Hack to work around the fact that the console driver on the
+ * simulator is always non-blocking.
+ */
+
+ if (i == CONSNDX)
+ {
+ if ((fds[CONSNDX].revents & POLLIN) != 0)
+ {
+ buffer[0] = getchar();
+ nbytes = 1;
+ }
+ else
+ {
+ nbytes = 0;
+ }
+ }
+ else
+#endif
+ {
+ /* The pipe works differently, it returns whatever data
+ * it has available without blocking.
+ */
+
+ nbytes = read(fds[i].fd, buffer, 63);
+ }
+
+ if (nbytes <= 0)
+ {
+ 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[%d] '%s' (%d bytes)\n", i, buffer, nbytes);
+ }
+
+ /* 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();
+ }
+
+ /* Won't get here */
+
+ (void)close(fd);
+ return NULL;
+}
diff --git a/apps/examples/poll/poll_main.c b/apps/examples/poll/poll_main.c
new file mode 100644
index 000000000..d66e7f269
--- /dev/null
+++ b/apps/examples/poll/poll_main.c
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * examples/poll/poll_main.c
+ *
+ * Copyright (C) 2008, 2011 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "poll_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: user_initialize
+ ****************************************************************************/
+
+void user_initialize(void)
+{
+}
+
+/****************************************************************************
+ * Name: user_start
+ ****************************************************************************/
+
+int user_start(int argc, char *argv[])
+{
+ char buffer[64];
+ ssize_t nbytes;
+ pthread_t tid1;
+ pthread_t tid2;
+#ifdef HAVE_NETPOLL
+ pthread_t tid3;
+#endif
+ int count;
+ int fd1 = -1;
+ int fd2 = -1;
+ int ret;
+ int exitcode = 0;
+
+ /* Open FIFOs */
+
+ message("\nuser_start: Creating FIFO %s\n", FIFO_PATH1);
+ ret = mkfifo(FIFO_PATH1, 0666);
+ if (ret < 0)
+ {
+ message("user_start: mkfifo failed: %d\n", errno);
+ exitcode = 1;
+ goto errout;
+ }
+
+ message("\nuser_start: Creating FIFO %s\n", FIFO_PATH2);
+ ret = mkfifo(FIFO_PATH2, 0666);
+ if (ret < 0)
+ {
+ message("user_start: mkfifo failed: %d\n", errno);
+ exitcode = 2;
+ goto errout;
+ }
+
+ /* Open the FIFOs for blocking, write */
+
+ fd1 = open(FIFO_PATH1, O_WRONLY);
+ if (fd1 < 0)
+ {
+ message("user_start: Failed to open FIFO %s for writing, errno=%d\n",
+ FIFO_PATH1, errno);
+ exitcode = 3;
+ goto errout;
+ }
+
+ fd2 = open(FIFO_PATH2, O_WRONLY);
+ if (fd2 < 0)
+ {
+ message("user_start: Failed to open FIFO %s for writing, errno=%d\n",
+ FIFO_PATH2, errno);
+ exitcode = 4;
+ goto errout;
+ }
+
+ /* Start the listeners */
+
+ message("user_start: Starting poll_listener thread\n");
+
+ ret = pthread_create(&tid1, NULL, poll_listener, NULL);
+ if (ret != 0)
+ {
+ message("user_start: Failed to create poll_listener thread: %d\n", ret);
+ exitcode = 5;
+ goto errout;
+ }
+
+ message("user_start: Starting select_listener thread\n");
+
+ ret = pthread_create(&tid2, NULL, select_listener, NULL);
+ if (ret != 0)
+ {
+ message("user_start: Failed to create select_listener thread: %d\n", ret);
+ exitcode = 6;
+ goto errout;
+ }
+
+#ifdef HAVE_NETPOLL
+#ifdef CONFIG_NET_TCPBACKLOG
+ message("user_start: Starting net_listener thread\n");
+
+ ret = pthread_create(&tid3, NULL, net_listener, NULL);
+#else
+ message("user_start: Starting net_reader thread\n");
+
+ ret = pthread_create(&tid3, NULL, net_reader, NULL);
+#endif
+ if (ret != 0)
+ {
+ message("user_start: Failed to create net_listener thread: %d\n", ret);
+ }
+#endif
+
+ /* Loop forever */
+
+ for (count = 0; ; count++)
+ {
+ /* Send a message to the listener... this should wake the listener
+ * from the poll.
+ */
+
+ sprintf(buffer, "Message %d", count);
+ nbytes = write(fd1, buffer, strlen(buffer));
+ if (nbytes < 0)
+ {
+ message("user_start: Write to fd1 failed: %d\n", errno);
+ exitcode = 7;
+ goto errout;
+ }
+
+ nbytes = write(fd2, buffer, strlen(buffer));
+ if (nbytes < 0)
+ {
+ message("user_start: Write fd2 failed: %d\n", errno);
+ exitcode = 8;
+ goto errout;
+ }
+
+ message("\nuser_start: Sent '%s' (%d bytes)\n", buffer, nbytes);
+ msgflush();
+
+ /* Wait awhile. This delay should be long enough that the
+ * listener will timeout.
+ */
+
+ sleep(WRITER_DELAY);
+ }
+
+errout:
+ if (fd1 >= 0)
+ {
+ close(fd1);
+ }
+
+ if (fd2 >= 0)
+ {
+ close(fd2);
+ }
+
+ fflush(stdout);
+ return exitcode;
+}
diff --git a/apps/examples/poll/select_listener.c b/apps/examples/poll/select_listener.c
new file mode 100644
index 000000000..80039ada3
--- /dev/null
+++ b/apps/examples/poll/select_listener.c
@@ -0,0 +1,193 @@
+/****************************************************************************
+ * examples/poll/select_listener.c
+ *
+ * Copyright (C) 2008, 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/select.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <debug.h>
+
+#include "poll_internal.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: select_listener
+ ****************************************************************************/
+
+void *select_listener(pthread_addr_t pvarg)
+{
+ fd_set rfds;
+ struct timeval tv;
+ char buffer[64];
+ ssize_t nbytes;
+ bool timeout;
+ bool ready;
+ int fd;
+ int ret;
+
+ /* Open the FIFO for non-blocking read */
+
+ message("select_listener: Opening %s for non-blocking read\n", FIFO_PATH2);
+ fd = open(FIFO_PATH2, O_RDONLY|O_NONBLOCK);
+ if (fd < 0)
+ {
+ message("select_listener: ERROR Failed to open FIFO %s: %d\n",
+ FIFO_PATH2, errno);
+ (void)close(fd);
+ return (void*)-1;
+ }
+
+ /* Loop forever */
+
+ for (;;)
+ {
+ message("select_listener: Calling select()\n");
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ tv.tv_sec = SELECT_LISTENER_DELAY;
+ tv.tv_usec = 0;
+
+ timeout = false;
+ ready = false;
+
+ ret = select(fd+1, (FAR fd_set*)&rfds, (FAR fd_set*)NULL, (FAR fd_set*)NULL, &tv);
+ message("\nselect_listener: select returned: %d\n", ret);
+
+ if (ret < 0)
+ {
+ message("select_listener: ERROR select failed: %d\n");
+ }
+ else if (ret == 0)
+ {
+ message("select_listener: Timeout\n");
+ timeout = true;
+ }
+ else
+ {
+ if (ret != 1)
+ {
+ message("select_listener: ERROR poll reported: %d\n");
+ }
+ else
+ {
+ ready = true;
+ }
+
+ if (!FD_ISSET(fd, rfds))
+ {
+ message("select_listener: ERROR fd=%d not in fd_set\n");
+ }
+ }
+
+ /* In any event, read until the pipe is empty */
+
+ do
+ {
+ nbytes = read(fd, buffer, 63);
+ if (nbytes <= 0)
+ {
+ if (nbytes == 0 || errno == EAGAIN)
+ {
+ if (ready)
+ {
+ message("select_listener: ERROR no read data\n");
+ }
+ }
+ else if (errno != EINTR)
+ {
+ message("select_listener: read failed: %d\n", errno);
+ }
+ nbytes = 0;
+ }
+ else
+ {
+ if (timeout)
+ {
+ message("select_listener: ERROR? Poll timeout, but data read\n");
+ message(" (might just be a race condition)\n");
+ }
+
+ buffer[nbytes] = '\0';
+ message("select_listener: Read '%s' (%d bytes)\n", buffer, nbytes);
+ }
+
+ timeout = false;
+ ready = false;
+ }
+ while (nbytes > 0);
+
+ /* Make sure that everything is displayed */
+
+ msgflush();
+ }
+
+ /* Won't get here */
+
+ (void)close(fd);
+ return NULL;
+}