diff --git a/Documentation/NXGraphicsSubsystem.html b/Documentation/NXGraphicsSubsystem.html
index 41989057426e01e62ef74a427bee2d35362c31b3..6c3ccf7bbaefcfb409f98974e6cc850ae9bae28e 100644
--- a/Documentation/NXGraphicsSubsystem.html
+++ b/Documentation/NXGraphicsSubsystem.html
@@ -12,7 +12,7 @@
       <h1><big><font color="#3c34ec">
         <i>NX Graphics Subsystem</i>
       </font></big></h1>
-      <p>Last Updated: August 24, 2011</p>
+      <p>Last Updated: September 28, 2011</p>
     </td>
   </tr>
 </table>
@@ -3416,13 +3416,13 @@ static FAR const struct nx_fontpackage_s *g_fontpackages[] =
 <p><b>Building <code>apps/examples/nx</code></b>.
   NX testing was performed using <code>apps/examples/nx</code> with the
   Linux/Cygwin-based NuttX simulator.
-  Configuration files for building this test can be found in <code>configs/sim/nx</code>.
+  Configuration files for building this test can be found in <code>configs/sim/nx</code>
+  and <code>configs/sim/nx11</code>.
   There are two alternative configurations for building the simulation:
 </p>
 <ol>
   <li>
-    The default configuration using the configuration file at
-    <code>configs/sim/nx/defconfig</code>.
+    The configuration using the configuration file at <code>configs/sim/nx/defconfig</code>.
     This default configuration exercises the NX logic a 8 BPP but provides no visual feedback.
     In this configuration, a very simple, simulated framebuffer driver is used that is
     based upon a simple region of memory posing as video memory.
@@ -3437,18 +3437,17 @@ make
   </li>
   <li>
     <p>
-      A preferred configuration extends the test with a simulated framebuffer driver
+      The preferred configuration is at <code>configs/sim/nx11/defconfig</code>.
+      This configuration extends the test with a simulated framebuffer driver
       that uses an X window as a framebuffer.
-      This configuration uses the configuration file at <code>configs/sim/nx/defconfig-x11</code>.
       This is a superior test configuration because the X window appears at your desktop
       and you can see the NX output.
       This preferred configuration can be built as follows:
     </p>
 <ul><pre>
 cd &lt;NuttX-Directory&gt;/tools
-./configure sim/nx
+./configure sim/nx11
 cd  &lt;NuttX-Directory&gt;
-cp &lt;NuttX-Directory&gt;/configs/sim/nx/defconfig-x11 .config
 make
 ./nuttx
 </pre></ul>
@@ -3456,29 +3455,40 @@ make
       <i>Update:</i>
       The sim target has suffered some bit-rot over the years and so the following caveats need to be added:
       <ul>
-        <li>
-          The X target does not build under recent Cygwin configurations.
-        </li>
-        <li>
-          The X target does not build under current Ubuntu distributions;
-          it fails to locate the X header files.
-        </li>
-        <li>
+        <li><p>
+          The X target builds under recent Cygwin configurations, but does not execute.
+          (It fails inside of <code>XOpenDisplay()</code>.
+        </p></li>
+        <li><p>
+          The X target does not build under current (9.09) Ubuntu distributions.
+          I needed to make the following changes:
+        </p>
+        <ul></pre>
+cd /usr/lib/
+sudo ln -s libXext.so.6.4.0 libXext.so
+</pre></ul>
+        <p>
+          The build will also fail to locate the X header files unless you install an X11 development package.
+        </p></li>
+        <li><p>
           The sim target itself is broken under 64-bit Linux.
           This is because the sim target is based upon some assembly language setjmp/longjmp logic that only works on 32-bit systems.
-          <p><small><b>NOTE</b>: There is a workaround in this case: 
+        </p>
+        <p><small>
+          <b>NOTE</b>: There is a workaround in this case: 
           You can build for 32-bit execution on a 64-bit machine by adding <code>-m3</code> to the <code>CFLAGS</code> and <code>-m32 -m elf_i386</code> to the <code>LDFLAGS</code>.
           See the patch file <code>0001-Quick-hacks-to-build-sim-nsh-ostest-on-x86_64-as-32-.patch</code>
           that can be found in NuttX <a href="http://tech.groups.yahoo.com/group/nuttx/files">files</a>.
-          </small></p>
+        </small></p>
         </li>
+        <li><p>
+          Refer to the readme file in sim configuration
+          <a href="http://nuttx.svn.sourceforge.net/viewvc/nuttx/trunk/nuttx/configs/sim/README.txt?view=log">README.txt</a> file for additional information.
+        </p></li>
       </ul>
     </p>
   </li>
 </ol>
-<p>
-    Why isn't this configuration the default?  Because not all systems the use NX support X.
-</p>
 
 <p><b>Test Coverage</b>.
   At present, <code>apps/examples/nx</code>t only exercises a subset of NX;
@@ -3985,7 +3995,6 @@ make
 </tr>
 <tr>
   <td align="left" valign="top"><a href="#nxfconvertbpp"><code>nxf_convert_32bpp()</code></a></td>
-  <td>Use <code>defconfig-x11</code> when building.</td>
   <td align="center" bgcolor="skyblue">YES</td>
 </tr>
 </table></center>
diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile
index f7844a1d90f15bedef17d7a5875d0f7b152cbc76..0213a69dc2b7e97a3922cc1dd735a3a1d5a64c0e 100644
--- a/arch/sim/src/Makefile
+++ b/arch/sim/src/Makefile
@@ -53,6 +53,10 @@ else
   CSRCS += up_framebuffer.c
 ifeq ($(CONFIG_SIM_X11FB),y)
   HOSTSRCS += up_x11framebuffer.c
+ifeq ($(CONFIG_SIM_TOUCHSCREEN),y)
+  CSRCS += up_touchscreen.c
+  HOSTSRCS += up_x11eventloop.c
+endif
 endif
 endif
 
diff --git a/arch/sim/src/up_framebuffer.c b/arch/sim/src/up_framebuffer.c
index 298eb9f8a512eae115f9fad12035db395d3f430d..66292ca3b5f944197cb463fd68d686ec81e1a902 100644
--- a/arch/sim/src/up_framebuffer.c
+++ b/arch/sim/src/up_framebuffer.c
@@ -113,21 +113,6 @@ static int up_getcursor(FAR struct fb_vtable_s *vtable, FAR struct fb_cursorattr
 static int up_setcursor(FAR struct fb_vtable_s *vtable, FAR struct fb_setcursor_s *setttings);
 #endif
 
-/****************************************************************************
- * Public Function Prototypes
- ****************************************************************************/
-
-#ifdef CONFIG_SIM_X11FB
-extern int up_x11initialize(unsigned short width, unsigned short height,
-                            void **fbmem, unsigned int *fblen, unsigned char *bpp,
-                            unsigned short *stride);
-#ifdef CONFIG_FB_CMAP
-extern int up_x11cmap(unsigned short first, unsigned short len,
-                      unsigned char *red, unsigned char *green,
-                      unsigned char *blue, unsigned char  *transp);
-#endif
-#endif
-
 /****************************************************************************
  * Private Data
  ****************************************************************************/
diff --git a/arch/sim/src/up_initialize.c b/arch/sim/src/up_initialize.c
index 257be8ab55e7f511babed0e22acca81a4d631190..26207b624f6f9d0e7b3cf5fa6d8bc1bb05471dd8 100644
--- a/arch/sim/src/up_initialize.c
+++ b/arch/sim/src/up_initialize.c
@@ -44,6 +44,7 @@
 #include <nuttx/arch.h>
 #include <nuttx/fs.h>
 
+#include "os_internal.h"
 #include "up_internal.h"
 
 /****************************************************************************
@@ -98,10 +99,32 @@ void up_initialize(void)
   devnull_register();       /* Standard /dev/null */
   devzero_register();       /* Standard /dev/zero */
   up_devconsole();          /* Our private /dev/console */
+
 #if defined(CONFIG_FS_FAT) && !defined(CONFIG_DISABLE_MOUNTPOINT)
   up_registerblockdevice(); /* Our FAT ramdisk at /dev/ram0 */
 #endif
+
 #ifdef CONFIG_NET
   uipdriver_init();         /* Our "real" netwok driver */
 #endif
+
+  /* Start the X11 event loop and register the touchscreen driver */
+
+#if defined(CONFIG_SIM_X11FB) && defined(CONFIG_SIM_TOUCHSCREEN)
+  {
+    int ret;
+
+    /* Start the X11 event loop */
+
+    ret = KERNEL_THREAD("evloop", CONFIG_SIM_EVLOOPPRIORITY,
+                        CONFIG_SIM_EVLOOPSTACKSIZE,
+                        (main_t)up_x11eventloop, (const char **)NULL);
+    ASSERT(ret != ERROR);
+
+    /* Register the touchscreen driver */
+
+    ret = up_tcregister(0);
+    ASSERT(ret == OK);
+  }
+#endif
 }
diff --git a/arch/sim/src/up_internal.h b/arch/sim/src/up_internal.h
index 82df76e1f1fb9e8b8b4fd7a9fbb1ff54cea93117..19e50986b53f4a588b98af10d2cb3a1a476c1556 100644
--- a/arch/sim/src/up_internal.h
+++ b/arch/sim/src/up_internal.h
@@ -1,7 +1,7 @@
 /**************************************************************************
  * up_internal.h
  *
- *   Copyright (C) 2007, 2009 Gregory Nutt. All rights reserved.
+ *   Copyright (C) 2007, 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
@@ -45,26 +45,56 @@
 #include <nuttx/irq.h>
 
 /**************************************************************************
- * Public Definitions
+ * Pre-processor Definitions
  **************************************************************************/
+/* Configuration **********************************************************/
 
+#ifndef CONFIG_SIM_X11FB
+#  ifdef CONFIG_SIM_TOUCHSCREEN
+#    error "CONFIG_SIM_TOUCHSCREEN depends on CONFIG_SIM_X11FB"
+#    undef CONFIG_SIM_TOUCHSCREEN
+#  endif
+#endif
+
+#ifndef CONFIG_INPUT
+#  ifdef CONFIG_SIM_TOUCHSCREEN
+#    error "CONFIG_SIM_TOUCHSCREEN depends on CONFIG_INPUT"
+#    undef CONFIG_SIM_TOUCHSCREEN
+#  endif
+#endif
+
+#ifdef CONFIG_SIM_TOUCHSCREEN
+#  ifndef CONFIG_SIM_EVLOOPPRIORITY
+#    define CONFIG_SIM_EVLOOPPRIORITY 50
+#  endif
+#  ifndef CONFIG_SIM_EVLOOPSTACKSIZE
+#    define CONFIG_SIM_EVLOOPSTACKSIZE 4096
+#  endif
+#else
+#  undef CONFIG_SIM_EVLOOPPRIORITY
+#  undef CONFIG_SIM_EVLOOPSTACKSIZE
+#endif
+
+/* Context Switching Definitions ******************************************/
 /* Storage order: %ebx, $esi, %edi, %ebp, sp, and return PC */
+
 #ifdef __ASSEMBLY__
-# define JB_EBX (0*4)
-# define JB_ESI (1*4)
-# define JB_EDI (2*4)
-# define JB_EBP (3*4)
-# define JB_SP  (4*4)
-# define JB_PC  (5*4)
+#  define JB_EBX (0*4)
+#  define JB_ESI (1*4)
+#  define JB_EDI (2*4)
+#  define JB_EBP (3*4)
+#  define JB_SP  (4*4)
+#  define JB_PC  (5*4)
 #else
-# define JB_EBX (0)
-# define JB_ESI (1)
-# define JB_EDI (2)
-# define JB_EBP (3)
-# define JB_SP  (4)
-# define JB_PC  (5)
+#  define JB_EBX (0)
+#  define JB_ESI (1)
+#  define JB_EDI (2)
+#  define JB_EBP (3)
+#  define JB_SP  (4)
+#  define JB_PC  (5)
 #endif /* __ASSEMBLY__ */
 
+/* Simulated Heap Definitions **********************************************/
 /* Size of the simulated heap */
 
 #if CONFIG_MM_SMALL
@@ -73,6 +103,7 @@
 #  define SIM_HEAP_SIZE (4*1024*1024)
 #endif
 
+/* File System Definitions **************************************************/
 /* These definitions characterize the compressed filesystem image */
 
 #define BLOCK_COUNT         1024
@@ -126,6 +157,37 @@ extern size_t up_hostwrite(const void *buffer, size_t len);
 extern unsigned long up_getwalltime( void );
 #endif
 
+/* up_x11framebuffer.c ******************************************************/
+
+#ifdef CONFIG_SIM_X11FB
+extern int up_x11initialize(unsigned short width, unsigned short height,
+                            void **fbmem, unsigned int *fblen, unsigned char *bpp,
+                            unsigned short *stride);
+#ifdef CONFIG_FB_CMAP
+extern int up_x11cmap(unsigned short first, unsigned short len,
+                      unsigned char *red, unsigned char *green,
+                      unsigned char *blue, unsigned char  *transp);
+#endif
+#endif
+
+/* up_eventloop.c ***********************************************************/
+
+#ifdef CONFIG_SIM_X11FB
+#ifdef CONFIG_SIM_TOUCHSCREEN
+extern int up_x11eventloop(int argc, char *argv[]);
+#endif
+#endif
+
+/* up_eventloop.c ***********************************************************/
+
+#ifdef CONFIG_SIM_X11FB
+#ifdef CONFIG_SIM_TOUCHSCREEN
+extern int up_tcregister(int minor);
+extern int up_tcenter(int x, int y, int buttons);
+extern int up_tcleave(int x, int y, int buttons);
+#endif
+#endif
+
 /* up_tapdev.c ************************************************************/
 
 #if defined(CONFIG_NET) && !defined(__CYGWIN__)
diff --git a/arch/sim/src/up_touchscreen.c b/arch/sim/src/up_touchscreen.c
new file mode 100644
index 0000000000000000000000000000000000000000..09e4e013e2947e9578f7ee7f056cf2884850b5c8
--- /dev/null
+++ b/arch/sim/src/up_touchscreen.c
@@ -0,0 +1,753 @@
+/****************************************************************************
+ * arch/sim/src/up_touchscreen.c
+ *
+ *   Copyright (C) 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 <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <poll.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/arch.h>
+#include <nuttx/fs.h>
+
+#include <nuttx/input/touchscreen.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+
+/* Driver support ***********************************************************/
+/* This format is used to construct the /dev/input[n] device driver path.  It
+ * defined here so that it will be used consistently in all places.
+ */
+
+#define DEV_FORMAT   "/dev/input%d"
+#define DEV_NAMELEN  16
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This describes the state of one contact */
+
+enum up_contact_3
+{
+  CONTACT_NONE = 0,                    /* No contact */
+  CONTACT_DOWN,                        /* First contact */
+  CONTACT_MOVE,                        /* Same contact, possibly different position */
+  CONTACT_UP,                          /* Contact lost */
+};
+
+/* This structure describes the results of one touchscreen sample */
+
+struct up_sample_s
+{
+  uint8_t  id;                         /* Sampled touch point ID */
+  uint8_t  contact;                    /* Contact state (see enum up_contact_e) */
+  uint16_t x;                          /* Measured X position */
+  uint16_t y;                          /* Measured Y position */
+};
+
+/* This structure describes the state of one touchscreen driver instance */
+
+struct up_dev_s
+{
+  uint8_t nwaiters;                    /* Number of threads waiting for touchscreen data */
+  uint8_t id;                          /* Current touch point ID */
+  bool penchange;                      /* An unreported event is buffered */
+  sem_t devsem;                        /* Manages exclusive access to this structure */
+  sem_t waitsem;                       /* Used to wait for the availability of data */
+
+  struct up_sample_s sample;           /* Last sampled touch point data */
+
+  /* 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_touchscreen_NPOLLWAITERS];
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void up_notify(FAR struct up_dev_s *priv);
+static int up_sample(FAR struct up_dev_s *priv,
+                          FAR struct up_sample_s *sample);
+static int up_waitsample(FAR struct up_dev_s *priv,
+                              FAR struct up_sample_s *sample);
+static int up_transfer(FAR struct up_dev_s *priv, uint8_t cmd);
+static void up_worker(FAR void *arg);
+static int up_interrupt(int irq, FAR void *context);
+
+/* Character driver methods */
+
+static int up_open(FAR struct file *filep);
+static int up_close(FAR struct file *filep);
+static ssize_t up_read(FAR struct file *filep, FAR char *buffer, size_t len);
+static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+#ifndef CONFIG_DISABLE_POLL
+static int up_poll(FAR struct file *filep, struct pollfd *fds, bool setup);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This the the vtable that supports the character driver interface */
+
+static const struct file_operations up_fops =
+{
+  up_open,    /* open */
+  up_close,   /* close */
+  up_read,    /* read */
+  0,          /* write */
+  0,          /* seek */
+  up_ioctl    /* ioctl */
+#ifndef CONFIG_DISABLE_POLL
+  , up_poll   /* poll */
+#endif
+};
+
+/* Only one simulated touchscreen is supported o the the driver state
+ * structure may as well be pre-allocated.
+ */
+
+static struct up_dev_s g_simtouchscreen;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_notify
+ ****************************************************************************/
+
+static void up_notify(FAR struct up_dev_s *priv)
+{
+#ifndef CONFIG_DISABLE_POLL
+  int i;
+#endif
+
+  /* If there are threads waiting for read data, then signal one of them
+   * that the read data is available.
+   */
+
+  if (priv->nwaiters > 0)
+    {
+      /* After posting this semaphore, we need to exit because the touchscreen
+       * is no longer avaialable.
+       */
+
+      sem_post(&priv->waitsem); 
+    }
+
+  /* If there are threads waiting on poll() for touchscreen data to become availabe,
+   * then wake them up now.  NOTE: we wake up all waiting threads because we
+   * do not know that they are going to do.  If they all try to read the data,
+   * then some make end up blocking after all.
+   */
+
+#ifndef CONFIG_DISABLE_POLL
+  for (i = 0; i < CONFIG_touchscreen_NPOLLWAITERS; i++)
+    {
+      struct pollfd *fds = priv->fds[i];
+      if (fds)
+        {
+          fds->revents |= POLLIN;
+          ivdbg("Report events: %02x\n", fds->revents);
+          sem_post(fds->sem);
+        }
+    }
+#endif
+}
+
+/****************************************************************************
+ * Name: up_sample
+ ****************************************************************************/
+
+static int up_sample(FAR struct up_dev_s *priv,
+                     FAR struct up_sample_s *sample)
+{
+  int ret = -EAGAIN;
+
+  /* Is there new touchscreen sample data available? */
+
+  if (priv->penchange)
+    {
+      /* Yes.. the state has changed in some way.  Return a copy of the
+       * sampled data.
+       */
+
+      memcpy(sample, &priv->sample, sizeof(struct up_sample_s ));
+
+      /* Now manage state transitions */
+
+      if (sample->contact == CONTACT_UP)
+        {
+          /* Next.. no contract.  Increment the ID so that next contact ID will be unique */
+
+          priv->sample.contact = CONTACT_NONE;
+          priv->id++;
+        }
+      else if (sample->contact == CONTACT_DOWN)
+       {
+          /* First report -- next report will be a movement */
+
+         priv->sample.contact = CONTACT_MOVE;
+       }
+
+      priv->penchange = false;
+      ret = OK;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_waitsample
+ ****************************************************************************/
+
+static int up_waitsample(FAR struct up_dev_s *priv,
+                              FAR struct up_sample_s *sample)
+{
+  irqstate_t flags;
+  int ret;
+
+  /* Interrupts me be disabled when this is called to (1) prevent posting
+   * of semphores from interrupt handlers, and (2) to prevent sampled data
+   * from changing until it has been reported.
+   *
+   * In addition, we will also disable pre-emption to prevent other threads
+   * from getting control while we muck with the semaphores.
+   */
+
+  sched_lock();
+  flags = irqsave();
+
+  /* Now release the semaphore that manages mutually exclusive access to
+   * the device structure.  This may cause other tasks to become ready to
+   * run, but they cannot run yet because pre-emption is disabled.
+   */
+
+  sem_post(&priv->devsem);
+
+  /* Try to get the a sample... if we cannot, then wait on the semaphore
+   * that is posted when new sample data is availble.
+   */
+
+  while (up_sample(priv, sample) < 0)
+    {
+      /* Wait for a change in the touchscreen state */
+ 
+      priv->nwaiters++;
+      ret = sem_wait(&priv->waitsem);
+      priv->nwaiters--;
+
+      if (ret < 0)
+        {
+          /* If we are awakened by a signal, then we need to return
+           * the failure now.
+           */
+
+          DEBUGASSERT(errno == EINTR);
+          ret = -EINTR;
+          goto errout;
+        }
+    }
+
+  /* Re-acquire the the semaphore that manages mutually exclusive access to
+   * the device structure.  We may have to wait here.  But we have our sample.
+   * Interrupts and pre-emption will be re-enabled while we wait.
+   */
+
+  ret = sem_wait(&priv->devsem);
+
+errout:
+  /* Then re-enable interrupts.  We might get interrupt here and there
+   * could be a new sample.  But no new threads will run because we still
+   * have pre-emption disabled.
+   */
+
+  irqrestore(flags);
+
+  /* Restore pre-emption.  We might get suspended here but that is okay
+   * because we already have our sample.  Note:  this means that if there
+   * were two threads reading from the touchscreen for some reason, the data
+   * might be read out of order.
+   */
+
+  sched_unlock();
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_open
+ ****************************************************************************/
+
+static int up_open(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_close
+ ****************************************************************************/
+
+static int up_close(FAR struct file *filep)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_read
+ ****************************************************************************/
+
+static ssize_t up_read(FAR struct file *filep, FAR char *buffer, size_t len)
+{
+  FAR struct inode          *inode;
+  FAR struct up_dev_s  *priv;
+  FAR struct touch_sample_s *report;
+  struct up_sample_s    sample;
+  int                        ret;
+
+  DEBUGASSERT(filep);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode && inode->i_private);
+  priv  = (FAR struct up_dev_s *)inode->i_private;
+
+  /* Verify that the caller has provided a buffer large enough to receive
+   * the touch data.
+   */
+
+  if (len < SIZEOF_TOUCH_SAMPLE_S(1))
+    {
+      /* We could provide logic to break up a touch report into segments and
+       * handle smaller reads... but why?
+       */
+
+      return -ENOSYS;
+    }
+
+  /* Get exclusive access to the driver data structure */
+
+  ret = sem_wait(&priv->devsem);
+  if (ret < 0)
+    {
+      /* This should only happen if the wait was canceled by an signal */
+
+      DEBUGASSERT(errno == EINTR);
+      return -EINTR;
+    }
+
+  /* Try to read sample data. */
+
+  ret = up_sample(priv, &sample);
+  if (ret < 0)
+    {
+      /* Sample data is not available now.  We would ave to wait to get
+       * receive sample data.  If the user has specified the O_NONBLOCK
+       * option, then just return an error.
+       */
+
+      if (filep->f_oflags & O_NONBLOCK)
+        {
+          ret = -EAGAIN;
+          goto errout;
+       }
+
+      /* Wait for sample data */
+
+      ret = up_waitsample(priv, &sample);
+      if (ret < 0)
+        {
+          /* We might have been awakened by a signal */
+
+          goto errout;
+        }
+    }
+
+  /* In any event, we now have sampled touchscreen data that we can report
+   * to the caller.
+   */
+
+  report = (FAR struct touch_sample_s *)buffer;
+  memset(report, 0, SIZEOF_TOUCH_SAMPLE_S(1));
+  report->npoints            = 1;
+  report->point[0].id        = priv->id;
+  report->point[0].x         = sample.x;
+  report->point[0].y         = sample.y;
+  report->point[0].pressure  = 42;
+
+  /* Report the appropriate flags */
+
+  if (sample.contact == CONTACT_UP)
+    {
+      /* Pen is now up */
+
+      report->point[0].flags  = TOUCH_UP | TOUCH_ID_VALID;
+    }
+  else if (sample.contact == CONTACT_DOWN)
+    {
+      /* First contact */
+
+      report->point[0].flags  = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID;
+    }
+  else /* if (sample->contact == CONTACT_MOVE) */
+    {
+      /* Movement of the same contact */
+
+      report->point[0].flags  = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID | TOUCH_PRESSURE_VALID;
+    }
+
+  ret = SIZEOF_TOUCH_SAMPLE_S(1);
+
+errout:
+  sem_post(&priv->devsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name:up_ioctl
+ ****************************************************************************/
+
+static int up_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode         *inode;
+  FAR struct up_dev_s *priv;
+  int                       ret;
+
+  ivdbg("cmd: %d arg: %ld\n", cmd, arg);
+  DEBUGASSERT(filep);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode && inode->i_private);
+  priv  = (FAR struct up_dev_s *)inode->i_private;
+
+  /* Get exclusive access to the driver data structure */
+
+  ret = sem_wait(&priv->devsem);
+  if (ret < 0)
+    {
+      /* This should only happen if the wait was canceled by an signal */
+
+      DEBUGASSERT(errno == EINTR);
+      return -EINTR;
+    }
+
+  /* Process the IOCTL by command */
+
+  switch (cmd)
+    {
+      default:
+        ret = -ENOTTY;
+        break;
+    }
+
+  sem_post(&priv->devsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_poll
+ ****************************************************************************/
+
+#ifndef CONFIG_DISABLE_POLL
+static int up_poll(FAR struct file *filep, FAR struct pollfd *fds,
+                        bool setup)
+{
+  FAR struct inode         *inode;
+  FAR struct up_dev_s *priv;
+  pollevent_t               eventset;
+  int                       ndx;
+  int                       ret = OK;
+  int                       i;
+
+  ivdbg("setup: %d\n", (int)setup);
+  DEBUGASSERT(filep && fds);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode && inode->i_private);
+  priv  = (FAR struct up_dev_s *)inode->i_private;
+
+  /* Are we setting up the poll?  Or tearing it down? */
+
+  ret = sem_wait(&priv->devsem);
+  if (ret < 0)
+    {
+      /* This should only happen if the wait was canceled by an signal */
+
+      DEBUGASSERT(errno == EINTR);
+      return -EINTR;
+    }
+
+  if (setup)
+    {
+      /* Ignore waits that do not include POLLIN */
+
+      if ((fds->revents & POLLIN) == 0)
+        {
+          ret = -EDEADLK;
+          goto errout;
+        }
+
+      /* This is a request to set up the poll.  Find an available
+       * slot for the poll structure reference
+       */
+
+      for (i = 0; i < CONFIG_touchscreen_NPOLLWAITERS; i++)
+        {
+          /* Find an available slot */
+
+          if (!priv->fds[i])
+            {
+              /* Bind the poll structure and this slot */
+
+              priv->fds[i] = fds;
+              fds->priv    = &priv->fds[i];
+              break;
+            }
+        }
+
+      if (i >= CONFIG_touchscreen_NPOLLWAITERS)
+        {
+          fds->priv    = NULL;
+          ret          = -EBUSY;
+          goto errout;
+        }
+
+      /* Should we immediately notify on any of the requested events? */
+
+      if (priv->penchange)
+        {
+          up_notify(priv);
+        }
+    }
+  else if (fds->priv)
+    {
+      /* This is a request to tear down the poll. */
+
+      struct pollfd **slot = (struct pollfd **)fds->priv;
+      DEBUGASSERT(slot != NULL);
+
+      /* Remove all memory of the poll setup */
+
+      *slot                = NULL;
+      fds->priv            = NULL;
+    }
+
+errout:
+  sem_post(&priv->devsem);
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_tcregister
+ *
+ * Description:
+ *   Configure the touchscreen to use the provided I2C device instance.  This
+ *   will register the driver as /dev/inputN where N is the minor device
+ *   number
+ *
+ * Input Parameters:
+ *   dev     - An I2C driver instance
+ *   minor   - The input device minor number
+ *
+ * Returned Value:
+ *   Zero is returned on success.  Otherwise, a negated errno value is
+ *   returned to indicate the nature of the failure.
+ *
+ ****************************************************************************/
+
+int up_tcregister(int minor)
+{
+  FAR struct up_dev_s *priv;
+  char devname[DEV_NAMELEN];
+  int ret;
+
+  ivdbg("dev: %p minor: %d\n", dev, minor);
+
+  /* Debug-only sanity checks */
+
+  DEBUGASSERT(minor >= 0 && minor < 100);
+
+  /* Create and initialize a touchscreen device driver instance */
+
+  priv = &g_simtouchscreen;
+
+  /* Initialize the touchscreen device driver instance */
+
+  memset(priv, 0, sizeof(struct up_dev_s));
+  sem_init(&priv->devsem,  0, 1); /* Initialize device structure semaphore */
+  sem_init(&priv->waitsem, 0, 0); /* Initialize pen event wait semaphore */
+
+  /* Register the device as an input device */
+
+  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor);
+  ivdbg("Registering %s\n", devname);
+
+  ret = register_driver(devname, &up_fops, 0666, priv);
+  if (ret < 0)
+    {
+      idbg("register_driver() failed: %d\n", ret);
+      goto errout_with_priv;
+    }
+
+  /* And return success (?) */
+
+  return OK;
+
+errout_with_priv:
+  sem_destroy(&priv->devsem);
+#ifdef CONFIG_touchscreen_MULTIPLE
+  kfree(priv);
+#endif
+  return ret;
+}
+
+/****************************************************************************
+ * Name: up_tcenter
+ ****************************************************************************/
+
+int up_tcenter(int x, int y, int buttons)
+{
+  FAR struct up_dev_s *priv = (FAR struct up_dev_s *)&g_simtouchscreen;
+  bool                         pendown;  /* true: pend is down */
+
+  /* Any button press will count as pendown. */
+
+  pendown = (buttons != 0);
+
+  /* Handle the change from pen down to pen up */
+
+  if (!pendown)
+    {
+      /* Ignore the pend up if the pen was already up (CONTACT_NONE == pen up and
+       * already reported.  CONTACT_UP == pen up, but not reported)
+       */
+
+      if (priv->sample.contact == CONTACT_NONE)
+        {
+          return OK;
+        }
+
+      /* Not yet reported */
+
+      priv->sample.contact = CONTACT_UP;
+    }
+  else
+    {
+      /* Save the measurements */
+
+      priv->sample.x = x;
+      priv->sample.y = y;
+
+      /* Note the availability of new measurements */
+      /* If this is the first (acknowledged) pen down report, then report
+       * this as the first contact.  If contact == CONTACT_DOWN, it will be
+       * set to set to CONTACT_MOVE after the contact is first sampled.
+       */
+
+      if (priv->sample.contact != CONTACT_MOVE)
+        {
+          /* First contact */
+
+          priv->sample.contact = CONTACT_DOWN;
+        }
+    }
+
+  /* Indicate the availability of new sample data for this ID */
+
+  priv->sample.id = priv->id;
+  priv->penchange = true;
+
+  /* Notify any waiters that nes touchscreen data is available */
+
+  up_notify(priv);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: up_tcleave
+ ****************************************************************************/
+
+int up_tcleave(int x, int y, int buttons)
+{
+  FAR struct up_dev_s *priv = (FAR struct up_dev_s *)&g_simtouchscreen;
+
+  /* Treat leaving as penup */
+
+  /* Ignore the pen up if the pen was already up (CONTACT_NONE == pen up and
+   * already reported.  CONTACT_UP == pen up, but not reported)
+   */
+
+  if (priv->sample.contact != CONTACT_NONE)
+    {
+      priv->sample.contact = CONTACT_UP;
+    }
+  return OK;
+}
+
+
diff --git a/arch/sim/src/up_x11eventloop.c b/arch/sim/src/up_x11eventloop.c
new file mode 100644
index 0000000000000000000000000000000000000000..d28a03ab90d8b1a5e34db1e8d923cd8e0d97c5ed
--- /dev/null
+++ b/arch/sim/src/up_x11eventloop.c
@@ -0,0 +1,168 @@
+/****************************************************************************
+ * arch/sim/src/up_x11eventloop.c
+ *
+ *   Copyright (C) 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 <stdio.h>
+#include <X11/Xlib.h>
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Type Declarations
+ ***************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+extern int up_tcenter(int x, int y, int buttons);
+extern int up_tcleave(int x, int y, int buttons);
+
+/****************************************************************************
+ * Public Variables
+ ****************************************************************************/
+
+/* Defined in up_x11framebuffer.c */
+
+extern Display *g_display;
+extern Window g_window;
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Functions
+ ***************************************************************************/
+
+/****************************************************************************
+ * Name: up_x11eventloop
+ ***************************************************************************/
+
+static int up_buttonmap(int state)
+{
+  int ret = 0;
+
+  /* Remove any X11 dependencies.  Possible bit settings include:  Button1Mask,
+   * Button2Mask, Button3Mask, Button4Mask, Button5Mask, ShiftMask, LockMask,
+   * ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask.  I assume
+   * that for a mouse device Button1Mask, Button2Mask, and Button3Mask are
+   * sufficient.
+   */
+
+  if ((state & Button1Mask) != 0)
+    {
+      ret |= 1;
+    }
+
+  if ((state & Button2Mask) != 0)
+    {
+      ret |= 2;
+    }
+
+  if ((state & Button3Mask) != 0)
+    {
+      ret |= 4;
+    }
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ***************************************************************************/
+
+/****************************************************************************
+ * Name: up_x11eventloop
+ ***************************************************************************/
+
+int up_x11eventloop(int argc, char *argv[])
+{
+  XEvent event;
+  int ret;
+
+  /* Grab the pointer (mouse) */
+
+  ret = XGrabPointer(g_display, g_window, 0,
+                     EnterWindowMask|LeaveWindowMask,
+                     GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
+  if (ret != GrabSuccess)
+    {
+      fprintf(stderr, "Failed grap pointer\n");
+      return -1;
+    }
+
+  /* Then loop forever, waiting for events and processing events as they are
+   * received.
+   */
+ 
+  for (;;)
+    {
+      XNextEvent(g_display, &event);
+      switch (event.type)
+        {
+          case EnterNotify:
+            {
+              fprintf(stderr, "EnterNotify event: (%d,%d) %08x\n",
+                      event.xcrossing.x, event.xcrossing.y, event.xcrossing.state);
+              up_tcenter(event.xcrossing.x, event.xcrossing.y,
+                         up_buttonmap(event.xcrossing.state));
+            }
+            break;
+
+          case LeaveNotify :
+            {
+              fprintf(stderr, "LeaveNotify event: (%d,%d) %08x\n",
+                      event.xcrossing.x, event.xcrossing.y, event.xcrossing.state);
+              up_tcleave(event.xcrossing.x, event.xcrossing.y,
+                         up_buttonmap(event.xcrossing.state));
+            }
+            break;
+
+          default :
+            fprintf(stderr, "Unrecognized event: %d\n", event.type);
+            break;
+        }
+    }
+  return 0;
+}
diff --git a/arch/sim/src/up_x11framebuffer.c b/arch/sim/src/up_x11framebuffer.c
index 0aa58a6a7c2bfd0c8bc5fb8108225b8abd4224c4..ad02625de3946799cd33921b138fe3ccfea3f4a7 100644
--- a/arch/sim/src/up_x11framebuffer.c
+++ b/arch/sim/src/up_x11framebuffer.c
@@ -64,16 +64,19 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Global Variables
+ * Public Variables
  ****************************************************************************/
 
+/* Also used in up_x11eventloop */
+
+Display *g_display;
+Window g_window;
+
 /****************************************************************************
  * Private Variables
  ****************************************************************************/
 
-static Display *g_display;
 static int g_screen;
-static Window g_window;
 static GC g_gc;
 #ifndef CONFIG_SIM_X11NOSHM
 static XShmSegmentInfo g_xshminfo;
@@ -438,4 +441,3 @@ void up_x11update(void)
     }
   XSync(g_display, 0);
 }
-
diff --git a/configs/sim/README.txt b/configs/sim/README.txt
index 9d16abc37d67b8f796aec43eaf3d3f62c9eda579..d2fb92ccd3119f2959eaca4f9e54d230268ac2a3 100644
--- a/configs/sim/README.txt
+++ b/configs/sim/README.txt
@@ -68,7 +68,7 @@ X11 Issues
 ^^^^^^^^^^
 
 There is an X11-based framebuffer driver that you can use exercise the NuttX graphics
-subsystem on the simulator (see the sim/nx configuration below).  This may require a
+subsystem on the simulator (see the sim/nx11 configuration below).  This may require a
 lot of tinkering to get working, depending upon where your X11 installation stores
 libraries and header files and how it names libraries.
 
@@ -87,6 +87,9 @@ Configurations
 ^^^^^^^^^^^^^^
 
 mount
+
+  Description
+  -----------
   Configures to use examples/mount.  This configuration may be
   selected as follows:
 
@@ -95,6 +98,8 @@ mount
 
 nettest
 
+  Description
+  -----------
   Configures to use examples/nettest.  This configuration
   enables networking using the network TAP device.  It may
   be selected via:
@@ -118,6 +123,9 @@ nettest
     select the IP address that you want to use.
 
 nsh
+
+  Description
+  -----------
   Configures to use the NuttShell at examples/nsh.  This configuration
   may be selected as follows:
 
@@ -125,59 +133,112 @@ nsh
     ./configure.sh sim/nsh
 
 nx
+
+  Description
+  -----------
   Configures to use examples/nx.  This configuration may be
   selected as follows:
 
     cd <nuttx-directory>/tools
     ./configure.sh sim/nx
 
+  Special Framebuffer Configuration
+  ---------------------------------
   Special simulated framebuffer configuration options:
 
-  CONFIG_SIM_X11FB    - Use X11 window for framebuffer
-  CONFIG_SIM_FBHEIGHT - Height of the framebuffer in pixels
-  CONFIG_SIM_FBWIDTH  - Width of the framebuffer in pixels.
-  CONFIG_SIM_FBBPP    - Pixel depth in bits
+    CONFIG_SIM_FBHEIGHT - Height of the framebuffer in pixels
+    CONFIG_SIM_FBWIDTH  - Width of the framebuffer in pixels.
+    CONFIG_SIM_FBBPP    - Pixel depth in bits
+
+  No Display!
+  -----------
+  This version has NO DISPLAY and is only useful for debugging NX
+  internals in environments where X11 is not supported.  There is
+  and additonal configuration that may be added to include an X11-
+  based simulated framebuffer driver:
+  
+    CONFIG_SIM_X11FB    - Use X11 window for framebuffer
+
+  See the nx11 configuration below for more information.
+
+  Multi- and Single-User Modes
+  ----------------------------
+  The default is the single-user NX implementation.  To select
+  the multi-user NX implementation:
+
+    CONFG_NX_MULTIUSER=y
+    CONFIG_DISABLE_MQUEUE=n
+
+nx11
+
+  Description
+  -----------
+  Configures to use examples/nx.  This configuration is similar
+  to the nx configuration except that it addes support for an X11-
+  based framebuffer driver.  Of course, this configuration can only
+  be used in environments that support X11!  (And it may not even
+  be usable in all of those environments without some "tweaking").
+  
+  This configuration may be selected as follows:
 
-  NOTES:
-  - If CONFIG_SIM_X11FB is selected then the following are
-    needed
+    cd <nuttx-directory>/tools
+    ./configure.sh sim/nx11
 
-      CONFIG_SIM_FBBPP (must match the resolution of the display).
-      CONFIG_FB_CMAP=y
+  Special Framebuffer Configuration
+  ---------------------------------
+  This configuration uses the same special simulated framebuffer
+  configuration options as the nx configuration:
 
-    My system has 24-bit color, but packed into 32-bit words so
-    the correct seeting of CONFIG_SIM_FBBPP is 32.
+    CONFIG_SIM_X11FB    - Use X11 window for framebuffer
+    CONFIG_SIM_FBHEIGHT - Height of the framebuffer in pixels
+    CONFIG_SIM_FBWIDTH  - Width of the framebuffer in pixels.
+    CONFIG_SIM_FBBPP    - Pixel depth in bits
 
-  - For whatever value of CONFIG_SIM_FBBPP is selected, then
-    the corresponidng CONFIG_NX_DISABLE_*BPP setting must
-    not be disabled.
+  X11 Configuration
+  -----------------
+  But now, since CONFIG_SIM_X11FB is also selected the following
+  definitions are needed
 
-  - The default in defconfig is to use a generic memory buffer
-    for the framebuffer.  defconfig-x11 is an example with X11
-    support enabled.  To use this configuration you have to
-    configure as follows:
+    CONFIG_SIM_FBBPP (must match the resolution of the display).
+    CONFIG_FB_CMAP=y
 
-    cd tools
-    ./configure.sh sim/nx
-    cd ..
-    cp configs/sim/nx/defconfig-x11 .config
+  My system has 24-bit color, but packed into 32-bit words so
+  the correct seeting of CONFIG_SIM_FBBPP is 32.
+
+  For whatever value of CONFIG_SIM_FBBPP is selected, the
+  corresponidng CONFIG_NX_DISABLE_*BPP setting must not be
+  disabled.
 
-  - The default is the single-user NX implementation.  To select
-    the multi-user NX implementation:
+  Touchscreen Support
+  -------------------
+  A X11 mouse-based touchscreen simulation can also be enabled
+  by setting:
 
-      CONFG_NX_MULTIUSER=y
-      CONFIG_DISABLE_MQUEUE=n
+    CONFIG_INPUT=y
+    CONFIG_SIM_TOUCHSCREEN=y
 
-  - To get the system to compile under various X11 installations
-    you may have to modify a few things.  For example, in order
-    to find libXext, I had to make the following change under
-    Ubuntu 9.09:
+  X11 Build Issues
+  ----------------
+  To get the system to compile under various X11 installations
+  you may have to modify a few things.  For example, in order
+  to find libXext, I had to make the following change under
+  Ubuntu 9.09:
 
     cd /usr/lib/
     sudo ln -s libXext.so.6.4.0 libXext.so
 
+  Multi- and Single-User Modes
+  ----------------------------
+  The default is the single-user NX implementation.  To select
+  the multi-user NX implementation:
+
+    CONFG_NX_MULTIUSER=y
+    CONFIG_DISABLE_MQUEUE=n
+
 ostest
 
+  Description
+  -----------
   The "standard" NuttX examples/ostest configuration.  This
   configuration may be selected as follows:
 
@@ -186,6 +247,8 @@ ostest
 
 pashello
 
+  Description
+  -----------
   Configures to use examples/pashello.  This configuration may
   by selected as follows:
 
diff --git a/configs/sim/nx11/Make.defs b/configs/sim/nx11/Make.defs
new file mode 100644
index 0000000000000000000000000000000000000000..642dfbaf8c9d8634469c17ef7db9ba15149f5ccc
--- /dev/null
+++ b/configs/sim/nx11/Make.defs
@@ -0,0 +1,110 @@
+############################################################################
+# configs/sim/nx11/Make.defs
+#
+#   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.
+#
+############################################################################
+
+include ${TOPDIR}/.config
+
+HOSTOS			= ${shell uname -o 2>/dev/null || echo "Other"}
+
+ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
+  ARCHOPTIMIZATION	= -g
+else
+  ARCHOPTIMIZATION	= -O2
+endif
+
+ARCHCPUFLAGS		= -fno-builtin
+ARCHPICFLAGS		= -fpic
+ARCHWARNINGS		= -Wall -Wstrict-prototypes -Wshadow
+ARCHDEFINES		=
+ARCHINCLUDES		= -I. -isystem $(TOPDIR)/include
+ARCHSCRIPT		=
+
+CROSSDEV		=
+CC			= $(CROSSDEV)gcc
+CPP			= $(CROSSDEV)gcc -E
+LD			= $(CROSSDEV)ld
+AR			= $(CROSSDEV)ar rcs
+NM			= $(CROSSDEV)nm
+OBJCOPY			= $(CROSSDEV)objcopy
+OBJDUMP			= $(CROSSDEV)objdump
+
+CFLAGS			= $(ARCHWARNINGS) $(ARCHOPTIMIZATION) \
+			  $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
+CPPFLAGS		= $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
+AFLAGS			= $(CFLAGS) -D__ASSEMBLY__
+
+OBJEXT			= .o
+LIBEXT			= .a
+
+ifeq ($(HOSTOS),Cygwin)
+  EXEEXT		= .exe
+else
+  EXEEXT		=
+endif
+
+ifeq ("${CONFIG_DEBUG_SYMBOLS}","y")
+  LDFLAGS		+= -g
+endif
+
+define PREPROCESS
+	@echo "CPP: $1->$2"
+	@$(CPP) $(CPPFLAGS) $1 -o $2
+endef
+
+define COMPILE
+	@echo "CC: $1"
+	@$(CC) -c $(CFLAGS) $1 -o $2
+endef
+
+define ASSEMBLE
+	@echo "AS: $1"
+	@$(CC) -c $(AFLAGS) $1 -o $2
+endef
+
+define ARCHIVE
+	echo "AR: $2"; \
+	$(AR) $1 $2 || { echo "$(AR) $1 $2 FAILED!" ; exit 1 ; }
+endef
+
+define CLEAN
+	@rm -f *.o *.a
+endef
+
+MKDEP			= $(TOPDIR)/tools/mkdeps.sh
+
+HOSTCC			= gcc
+HOSTINCLUDES		= -I.
+HOSTCFLAGS		= $(ARCHWARNINGS) $(ARCHOPTIMIZATION) \
+			  $(ARCHCPUFLAGS) $(HOSTINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
+HOSTLDFLAGS		=
diff --git a/configs/sim/nx11/appconfig b/configs/sim/nx11/appconfig
new file mode 100644
index 0000000000000000000000000000000000000000..d99648abcce36f6cd65a368618f0148681327337
--- /dev/null
+++ b/configs/sim/nx11/appconfig
@@ -0,0 +1,39 @@
+############################################################################
+# configs/sim/nx11/appconfig
+#
+#   Copyright (C) 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.
+#
+############################################################################
+
+# Path to example in apps/examples containing the user_start entry point
+
+CONFIGURED_APPS += examples/nx
+
diff --git a/configs/sim/nx/defconfig-x11 b/configs/sim/nx11/defconfig
similarity index 98%
rename from configs/sim/nx/defconfig-x11
rename to configs/sim/nx11/defconfig
index 9228786dfea98d8cc3757a4653ef0ad66668285e..420231d48eb1f08bba23cfcd392fb92f2e488322 100644
--- a/configs/sim/nx/defconfig-x11
+++ b/configs/sim/nx11/defconfig
@@ -1,7 +1,7 @@
 ############################################################################
-# sim/nx/defconfig
+# sim/nx11/defconfig
 #
-#   Copyright (C) 2008, 2010 Gregory Nutt. All rights reserved.
+#   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
@@ -51,11 +51,19 @@ CONFIG_ARCH_BOARD_SIM=y
 
 #
 # Simulated framebuffer configuration
+#
 CONFIG_SIM_X11FB=y
 CONFIG_SIM_FBWIDTH=480
 CONFIG_SIM_FBHEIGHT=240
 CONFIG_SIM_FBBPP=32
 
+#
+# Simulated touchscreen configuration
+# (Set both of the following to 'y' to enable)
+#
+CONFIG_INPUT=n
+CONFIG_SIM_TOUCHSCREEN=n
+
 #
 # General OS setup
 #
diff --git a/configs/sim/nx11/setenv.sh b/configs/sim/nx11/setenv.sh
new file mode 100755
index 0000000000000000000000000000000000000000..dd51ecec2558cf5f6dd2ebc5928d046ab1128285
--- /dev/null
+++ b/configs/sim/nx11/setenv.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+# sim/nx11/setenv.sh
+#
+#   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.
+#
+
+if [ "$(basename $0)" = "setenv.sh" ] ; then
+  echo "You must source this script, not run it!" 1>&2
+  exit 1
+fi
+
+if [ -z ${PATH_ORIG} ]; then export PATH_ORIG=${PATH}; fi
+
+#export NUTTX_BIN=
+#export PATH=${NUTTX_BIN}:/sbin:/usr/sbin:${PATH_ORIG}
+
+echo "PATH : ${PATH}"