diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c
index 6c056b1dc2..78258d25ef 100755
--- a/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -85,10 +85,11 @@
 /* OHCI Setup ******************************************************************/
 /* Frame Interval / Periodic Start */
 
-#define  FI                     (12000-1) /* 12000 bits per frame (-1) */
-#define  FSMPS                  ((6 * (FI - 210)) / 7)
-#define  DEFAULT_FMINTERVAL     ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
-#define  DEFAULT_PERSTART       ((9 * FI) / 10)
+#define BITS_PER_FRAME          12000
+#define FI                     (BITS_PER_FRAME-1)
+#define FSMPS                  ((6 * (FI - 210)) / 7)
+#define DEFAULT_FMINTERVAL     ((FSMPS << OHCI_FMINT_FSMPS_SHIFT) | FI)
+#define DEFAULT_PERSTART       (((9 * BITS_PER_FRAME) / 10) - 1)
 
 /* CLKCTRL enable bits */
 
@@ -152,11 +153,15 @@ struct lpc17_usbhost_s
 
   /* Driver status */
 
-  volatile bool    connected; /* Connected to device */
-  volatile bool    lowspeed;  /* Low speed device attached. */
-  volatile bool    rhswait;   /* TRUE: Thread is waiting for Root Hub Status change */
-  sem_t            exclsem;   /* Support mutually exclusive access */
-  sem_t            rhssem;    /* Semaphore to wait Writeback Done Head event */
+  volatile bool    connected;   /* Connected to device */
+  volatile bool    lowspeed;    /* Low speed device attached. */
+  volatile bool    rhswait;     /* TRUE: Thread is waiting for Root Hub Status change */
+#ifndef CONFIG_USBHOST_INT_DISABLE
+  uint8_t          ininterval;  /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
+  uint8_t          outinterval; /* Minimum periodic IN EP polling interval: 2, 4, 6, 16, or 32 */
+#endif
+  sem_t            exclsem;     /* Support mutually exclusive access */
+  sem_t            rhssem;      /* Semaphore to wait Writeback Done Head event */
 };
 
 /* The OCHI expects the size of an endpoint descriptor to be 16 bytes.
@@ -174,7 +179,7 @@ struct lpc17_ed_s
   /* Software specific fields */
 
   uint8_t          xfrtype;   /* Transfer type.  See SB_EP_ATTR_XFER_* in usb.h */
-  uint8_t          period;    /* Periodic EP polling frequency 1, 2, 4, 6, 16, or 32 */
+  uint8_t          interval;  /* Periodic EP polling interval: 2, 4, 6, 16, or 32 */
   volatile uint8_t tdstatus;  /* TD control status bits from last Writeback Done Head event */
   volatile bool    wdhwait;   /* TRUE: Thread is waiting for WDH interrupt */
   sem_t            wdhsem;    /* Semaphore used to wait for Writeback Done Head event */
@@ -251,11 +256,20 @@ static inline int lpc17_addbulked(struct lpc17_usbhost_s *priv,
                                   struct lpc17_ed_s *ed);
 static inline int lpc17_rembulked(struct lpc17_usbhost_s *priv,
                                   struct lpc17_ed_s *ed);
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static unsigned int lpc17_getinterval(uint8_t interval);
+static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int offset);
+#endif
+
 static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
+                                 const FAR struct usbhost_epdesc_s *epdesc, 
                                  struct lpc17_ed_s *ed);
 static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
                                  struct lpc17_ed_s *ed);
+
 static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
+                                  const FAR struct usbhost_epdesc_s *epdesc, 
                                   struct lpc17_ed_s *ed);
 static inline int lpc17_remisoced(struct lpc17_usbhost_s *priv,
                                   struct lpc17_ed_s *ed);
@@ -722,9 +736,9 @@ static inline int lpc17_rembulked(struct lpc17_usbhost_s *priv,
                                   struct lpc17_ed_s *ed)
 {
 #ifndef CONFIG_USBHOST_BULK_DISABLE
-  struct lpc17_ed_s      *curr = NULL;
-  struct lpc17_ed_s      *prev = NULL;
-  uint32_t                regval;
+  struct lpc17_ed_s *curr;
+  struct lpc17_ed_s *prev;
+  uint32_t           regval;
 
   /* Find the ED in the bulk list.  NOTE: We really should never be mucking
    * with the bulk list while BLE is set.
@@ -773,44 +787,315 @@ static inline int lpc17_rembulked(struct lpc17_usbhost_s *priv,
 #endif
 }
 
+/*******************************************************************************
+ * Name: lpc17_getinterval
+ *
+ * Description:
+ *   Convert the endpoint polling interval into a HCCA table increment
+ *
+ *******************************************************************************/
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static unsigned int lpc17_getinterval(uint8_t interval)
+{
+  /* The bInterval field of the endpoint descriptor contains the polling interval
+   * for interrupt and isochronous endpoints. For other types of endpoint, this
+   * value should be ignored. bInterval is provided in units of 1MS frames.
+   */
+
+  if (interval < 3)
+    {
+      return 2;
+    }
+  else if (interval < 7)
+    {
+      return 4;
+    }
+  else if (interval < 15)
+    {
+      return 8;
+    }
+  else if (interval < 31)
+    {
+      return 16;
+    }
+  else
+    {
+      return 32;
+    }
+}
+#endif
+
+/*******************************************************************************
+ * Name: lpc17_setinttab
+ *
+ * Description:
+ *   Set the interrupt table to the selected value using the provided interval
+ *   and offset.
+ *
+ *******************************************************************************/
+
+#if !defined(CONFIG_USBHOST_INT_DISABLE) || !defined(CONFIG_USBHOST_ISOC_DISABLE)
+static void lpc17_setinttab(uint32_t value, unsigned int interval, unsigned int offset)
+{
+  unsigned int i;
+  for (i = offset; i < HCCA_INTTBL_WSIZE; i += interval)
+    {
+      HCCA->inttbl[i] = value;
+    }
+}
+#endif
+
 /*******************************************************************************
  * Name: lpc17_addinted
  *
  * Description:
  *   Helper function to add an ED to the HCCA interrupt table.
  *
+ *   To avoid reshuffling the table so much and to keep life simple in general,
+ *    the following rules are applied:
+ *
+ *     1. IN EDs get the even entries, OUT EDs get the odd entries.
+ *     2. Add IN/OUT EDs are scheduled together at the minimum interval of all
+ *        IN/OUT EDs.
+ *
+ *   This has the following consequences:
+ *
+ *     1. The minimum support polling rate is 2MS, and
+ *     2. Some devices may get polled at a much higher rate than they request.
+ *
  *******************************************************************************/
  
 static inline int lpc17_addinted(struct lpc17_usbhost_s *priv,
+                                 const FAR struct usbhost_epdesc_s *epdesc, 
                                  struct lpc17_ed_s *ed)
 {
 #ifndef CONFIG_USBHOST_INT_DISABLE
-#  warning "Interrupt endpoints not yet supported"
+  unsigned int interval;
+  unsigned int offset;
+  uint32_t head;
+  uint32_t regval;
+
+  /* Disable periodic list processing.  Does this take effect immediately?  Or
+   * at the next SOF... need to check.
+   */
+
+  regval  = lpc17_getreg(LPC17_USBHOST_CTRL);
+  regval &= ~OHCI_CTRL_PLE;
+  lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+
+  /* Get the quanitized interval value associated with this ED and save it
+   * in the ED.
+   */
+
+  interval     = lpc17_getinterval(epdesc->interval);
+  ed->interval = interval;
+  uvdbg("interval: %d->%d\n", epdesc->interval, interval);
+
+  /* Get the offset associated with the ED direction. IN EDs get the even
+   * entries, OUT EDs get the odd entries.
+   *
+   * Get the new, minimum interval. Add IN/OUT EDs are scheduled together
+   * at the minimum interval of all IN/OUT EDs.
+   */
+
+  if (epdesc->in)
+    {
+      offset = 0;
+      if (priv->ininterval > interval)
+        {
+          priv->ininterval = interval;
+        }
+      else
+        {
+          interval = priv->ininterval;
+        }
+    }
+  else
+    {
+      offset = 1;
+      if (priv->outinterval > interval)
+        {
+          priv->outinterval = interval;
+        }
+      else
+        {
+          interval = priv->outinterval;
+        }
+    }
+  uvdbg("min interval: %d offset: %d\n", interval, offset);
+
+  /* Get the head of the first of the duplicated entries.  The first offset
+   * entry is always guaranteed to contain the common ED list head.
+   */
+
+  head = HCCA->inttbl[offset];
+
+  /* Clear all current entries in the interrupt table for this direction */
+
+  lpc17_setinttab(0, 2, offset);
+
+  /* Add the new ED before the old head of the periodic ED list and set the
+   * new ED as the head ED in all of the appropriate entries of the HCCA
+   * interrupt table.
+   */
+
+  ed->hw.nexted = head;
+  lpc17_setinttab((uint32_t)ed, interval, offset);
+  uvdbg("head: %08x next: %08x\n", ed, head);
+
+  /* Re-enabled periodic list processing */
+
+  regval  = lpc17_getreg(LPC17_USBHOST_CTRL);
+  regval &= ~OHCI_CTRL_PLE;
+  lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+  return OK;
 #else
   return -ENOSYS;
 #endif
 }
 
 /*******************************************************************************
- * Name: lpc17_addbulked
+ * Name: lpc17_reminted
  *
  * Description:
  *   Helper function to remove an ED from the HCCA interrupt table.
  *
+ *   To avoid reshuffling the table so much and to keep life simple in general,
+ *    the following rules are applied:
+ *
+ *     1. IN EDs get the even entries, OUT EDs get the odd entries.
+ *     2. Add IN/OUT EDs are scheduled together at the minimum interval of all
+ *        IN/OUT EDs.
+ *
+ *   This has the following consequences:
+ *
+ *     1. The minimum support polling rate is 2MS, and
+ *     2. Some devices may get polled at a much higher rate than they request.
+ *
  *******************************************************************************/
  
 static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
                                  struct lpc17_ed_s *ed)
 {
 #ifndef CONFIG_USBHOST_INT_DISABLE
-#  warning "Interrupt endpoints not yet supported"
+  struct lpc17_ed_s *head;
+  struct lpc17_ed_s *curr;
+  struct lpc17_ed_s *prev;
+  unsigned int       interval;
+  unsigned int       offset;
+  uint32_t           regval;
+
+  /* Disable periodic list processing.  Does this take effect immediately?  Or
+   * at the next SOF... need to check.
+   */
+
+  regval  = lpc17_getreg(LPC17_USBHOST_CTRL);
+  regval &= ~OHCI_CTRL_PLE;
+  lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+
+  /* Get the offset associated with the ED direction. IN EDs get the even
+   * entries, OUT EDs get the odd entries.
+   */
+
+  if ((ed->hw.ctrl && ED_CONTROL_D_MASK) == ED_CONTROL_D_IN)
+    {
+      offset = 0;
+    }
+  else
+    {
+      offset = 1;
+    }
+
+  /* Get the head of the first of the duplicated entries.  The first offset
+   * entry is always guaranteed to contain the common ED list head.
+   */
+
+  head = (struct lpc17_ed_s *)HCCA->inttbl[offset];
+  uvdbg("ed: %08x head: %08x next: %08x offset: %d\n",
+        ed, head, head ? head->hw.nexted : 0, offset);
+
+  /* Find the ED to be removed in the ED list */
+
+  for (curr = head, prev = NULL;
+       curr && curr != ed;
+       prev = curr, curr = (struct lpc17_ed_s *)curr->hw.nexted);
+
+  /* Hmmm.. It would be a bug if we do not find the ED in the bulk list. */
+
+  DEBUGASSERT(curr != NULL);
+  if (curr != NULL)
+    {
+      /* Clear all current entries in the interrupt table for this direction */
+
+      lpc17_setinttab(0, 2, offset);
+
+      /* Remove the ED from the list..  Is this ED the first on in the list? */
+
+      if (prev == NULL)
+        {
+          /* Yes... set the head of the bulk list to skip over this ED */
+
+          head = (struct lpc17_ed_s *)ed->hw.nexted;
+        }
+      else
+        {
+          /* No.. set the forward link of the previous ED in the list
+           * skip over this ED.
+           */
+
+          prev->hw.nexted = ed->hw.nexted;
+        }
+        uvdbg("ed: %08x head: %08x next: %08x\n",
+              ed, head, head ? head->hw.nexted : 0);
+
+      /* Calculate the new minimum interval for this list */
+
+      interval = 32;
+      for (curr = head; curr; curr = (struct lpc17_ed_s *)curr->hw.nexted)
+        {
+          if (curr->interval < interval)
+            {
+              interval = curr->interval;
+            }
+        }
+      uvdbg("min interval: %d offset: %d\n", interval, offset);
+
+      /* Save the new minimum interval */
+ 
+      if ((ed->hw.ctrl && ED_CONTROL_D_MASK) == ED_CONTROL_D_IN)
+        {
+          priv->ininterval  = interval;
+        }
+      else
+        {
+          priv->outinterval = interval;
+        }
+
+      /* Set the head ED in all of the appropriate entries of the HCCA interrupt
+       * table (head might be NULL).
+       */
+
+      lpc17_setinttab((uint32_t)head, interval, offset);
+    }
+
+  /* Re-enabled periodic list processing */
+
+  if (head != NULL)
+    {
+      regval  = lpc17_getreg(LPC17_USBHOST_CTRL);
+      regval &= ~OHCI_CTRL_PLE;
+      lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+    }
+
+  return OK;
 #else
   return -ENOSYS;
 #endif
 }
 
 /*******************************************************************************
- * Name: lpc17_addbulked
+ * Name: lpc17_addisoced
  *
  * Description:
  *   Helper functions to add an ED to the periodic table.
@@ -818,6 +1103,7 @@ static inline int lpc17_reminted(struct lpc17_usbhost_s *priv,
  *******************************************************************************/
  
 static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
+                                  const FAR struct usbhost_epdesc_s *epdesc, 
                                   struct lpc17_ed_s *ed)
 {
 #ifndef CONFIG_USBHOST_ISOC_DISABLE
@@ -828,7 +1114,7 @@ static inline int lpc17_addisoced(struct lpc17_usbhost_s *priv,
 }
 
 /*******************************************************************************
- * Name: lpc17_addbulked
+ * Name: lpc17_remisoced
  *
  * Description:
  *   Helper functions to remove an ED from the periodic table.
@@ -1441,7 +1727,7 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
 
       /* Get the direction of the endpoint */
 
-      if (epdesc->in != 0)
+      if (epdesc->in)
         {
           ed->hw.ctrl |= ED_CONTROL_D_IN;
         }
@@ -1491,11 +1777,11 @@ static int lpc17_epalloc(FAR struct usbhost_driver_s *drvr,
           break;
 
         case USB_EP_ATTR_XFER_INT:
-          ret = lpc17_addinted(priv, ed);
+          ret = lpc17_addinted(priv, epdesc, ed);
           break;
 
         case USB_EP_ATTR_XFER_ISOC:
-          ret = lpc17_addisoced(priv, ed);
+          ret = lpc17_addisoced(priv, epdesc, ed);
           break;
 
         case USB_EP_ATTR_XFER_CONTROL:
diff --git a/drivers/usbhost/usbhost_hidkbd.c b/drivers/usbhost/usbhost_hidkbd.c
index 7cdc41b0b7..cf07ccc4ec 100644
--- a/drivers/usbhost/usbhost_hidkbd.c
+++ b/drivers/usbhost/usbhost_hidkbd.c
@@ -43,6 +43,7 @@
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <string.h>
 #include <poll.h>
 #include <semaphore.h>
@@ -53,7 +54,6 @@
 
 #include <nuttx/fs.h>
 #include <nuttx/arch.h>
-#include <nuttx/wqueue.h>
 
 #include <nuttx/usb/usb.h>
 #include <nuttx/usb/usbhost.h>
@@ -67,32 +67,32 @@
  * Pre-processor Definitions
  ****************************************************************************/
 /* Configuration ************************************************************/
-/* Worker thread support is required */
-
-#ifndef CONFIG_SCHED_WORKQUEUE
-#  error "Worker thread support is required (CONFIG_SCHED_WORKQUEUE)"
-#endif
-
 /* This determines how often the USB keyboard will be polled in units of
- * of clock ticks.  The default is 100MS.
+ * of microseconds.  The default is 100MS.
  */
 
-#ifndef CONFIG_HIDKBD_POLLTICKS
-  /* The value CLK_TCK gives the frequency in HZ of the system timer.  This
-   * is, the number of ticks in one second.  So one tenth of this would give
-   * is the number of ticks required for a 100MS delay between polls.
-   */
+#ifndef CONFIG_HIDKBD_POLLUSEC
+#  define CONFIG_HIDKBD_POLLUSEC (100*1000)
+#endif
 
-#  define CONFIG_HIDKBD_POLLTICKS (CLK_TCK/10)
+/* Signals must not be disabled as they are needed by usleep */
+
+/* Provide some default values for other configuration settings */
+
+#ifndef CONFIG_HIDKBD_DEFPRIO
+#  define CONFIG_HIDKBD_DEFPRIO 50
+#endif
+#ifndef CONFIG_HIDKBD_STACKSIZE
+#  define CONFIG_HIDKBD_STACKSIZE 1024
 #endif
 
 /* Driver support ***********************************************************/
-/* This format is used to construct the /dev/sd[n] device driver path.  It
+/* This format is used to construct the /dev/kbd[n] device driver path.  It
  * defined here so that it will be used consistently in all places.
  */
 
-#define DEV_FORMAT          "/dev/sd%c"
-#define DEV_NAMELEN         10
+#define DEV_FORMAT          "/dev/kbd%c"
+#define DEV_NAMELEN         11
 
 /* Used in usbhost_cfgdesc() */
 
@@ -107,8 +107,8 @@
  * Private Types
  ****************************************************************************/
 
-/* This structure contains the internal, private state of the USB host mass
- * storage class.
+/* This structure contains the internal, private state of the USB host
+ * keyboard storage class.
  */
 
 struct usbhost_state_s
@@ -121,15 +121,16 @@ struct usbhost_state_s
 
   struct usbhost_driver_s *drvr;
 
-  /* The remainder of the fields are provide o the mass storage class */
+  /* The remainder of the fields are provide o the keyboard class driver */
   
-  char                    sdchar;       /* Character identifying the /dev/sd[n] device */
+  char                    devchar;      /* Character identifying the /dev/kbd[n] device */
   volatile bool           disconnected; /* TRUE: Device has been disconnected */
+  volatile bool           polling;      /* TRUE: Poll thread is running */
   int16_t                 crefs;        /* Reference count on the driver instance */
   sem_t                   exclsem;      /* Used to maintain mutual exclusive access */
-  struct work_s           work;         /* For interacting with the worker thread */
-  FAR uint8_t            *tdbuffer;     /* The allocated transfer descriptor buffer */
-  size_t                  tdbuflen;     /* Size of the allocated transfer buffer */
+  FAR uint8_t            *tbuffer;      /* The allocated transfer buffer */
+  size_t                  tbuflen;      /* Size of the allocated transfer buffer */
+  pid_t                   pollpid;      /* PID of the poll task */
 
   /* Endpoints:
    * EP0 (Control):
@@ -167,10 +168,10 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
 static void usbhost_freedevno(FAR struct usbhost_state_s *priv);
 static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname);
 
-/* Worker thread actions */
+/* Keyboard polling thread */
 
-static void usbhost_kbdpoll(FAR void *arg);
-static void usbhost_destroy(FAR void *arg);
+static void usbhost_destroy(FAR struct usbhost_state_s *priv);
+static int usbhost_kbdpoll(int argc, char *argv[]);
 
 /* Helpers for usbhost_connect() */
 
@@ -205,12 +206,14 @@ static int usbhost_disconnected(FAR struct usbhost_class_s *class);
 
 /* Driver methods.  We export the keyboard as a standard character driver */
 
-static ssize_t usbhost_read(FAR struct file *filp,
+static int usbhost_open(FAR struct file *filep);
+static int usbhost_close(FAR struct file *filep);
+static ssize_t usbhost_read(FAR struct file *filep,
                             FAR char *buffer, size_t len);
-static ssize_t usbhost_write(FAR struct file *filp,
+static ssize_t usbhost_write(FAR struct file *filep,
                              FAR const char *buffer, size_t len);
 #ifndef CONFIG_DISABLE_POLL
-static int usbhost_poll(FAR struct file *filp, FAR struct pollfd *fds,
+static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
                         bool setup);
 #endif
 
@@ -219,7 +222,7 @@ static int usbhost_poll(FAR struct file *filp, FAR struct pollfd *fds,
  ****************************************************************************/
 
 /* This structure provides the registry entry ID informatino that will  be 
- * used to associate the USB host mass storage class to a connected USB
+ * used to associate the USB host keyboard class driver to a connected USB
  * device.
  */
 
@@ -244,8 +247,8 @@ static struct usbhost_registry_s g_skeleton =
 
 static const struct file_operations usbhost_fops =
 {
-  0,                       /* open      */
-  0,                       /* close     */
+  usbhost_open,            /* open      */
+  usbhost_close,           /* close     */
   usbhost_read,            /* read      */
   usbhost_write,           /* write     */
   0,                       /* seek      */
@@ -255,10 +258,16 @@ static const struct file_operations usbhost_fops =
 #endif
 };
 
-/* This is a bitmap that is used to allocate device names /dev/sda-z. */
+/* This is a bitmap that is used to allocate device names /dev/kbda-z. */
 
 static uint32_t g_devinuse;
 
+/* The following are used to managed the class creation operation */
+
+static sem_t                   g_exclsem; /* For mutually exclusive thread creation */
+static sem_t                   g_syncsem; /* Thread data passing interlock */
+static struct usbhost_state_s *g_priv;    /* Data passed to thread */
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -361,7 +370,7 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
       if ((g_devinuse & bitno) == 0)
         {
           g_devinuse |= bitno;
-          priv->sdchar = 'a' + devno;
+          priv->devchar = 'a' + devno;
           irqrestore(flags);
           return OK;
         }
@@ -373,7 +382,7 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
 
 static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
 {
-  int devno = 'a' - priv->sdchar;
+  int devno = 'a' - priv->devchar;
 
   if (devno >= 0 && devno < 26)
     {
@@ -385,80 +394,7 @@ static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
 
 static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname)
 {
-  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->sdchar);
-}
-
-/****************************************************************************
- * Name: usbhost_kbdpoll
- *
- * Description:
- *   Periodically check for new keyboard data.
- *
- * Input Parameters:
- *   arg - A reference to the class instance to be destroyed.
- *
- * Returned Values:
- *   None
- *
- ****************************************************************************/
-
-static void usbhost_kbdpoll(FAR void *arg)
-{
-  FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg;
-  irqstate_t flags;
-#ifdef CONFIG_DEBUG_USB
-  static unsigned int npolls = 0;
-#endif
-  int ret;
-
-  /* Poll the keyboard */
-#warning "Missing logic"
-
-  /* Setup for the next poll.  We have to be careful here because the work
-   * structure may be used by the interrupt handler if the USB device is
-   * disconnected.
-   */
-
-  flags = irqsave();
-
-  /* Is the device still connected?  If not, we do not reschedule any further
-   * polling of the device.
-   */
-
-  if (priv->disconnected)
-    {
-      udbg("Keyboard removed, polling halted\n");
-    }
-  else
-    {
-      /* Otherwise, just setup the next poll. */
- 
-      ret = work_queue(&priv->work, usbhost_kbdpoll, priv, CONFIG_HIDKBD_POLLTICKS);
-      if (ret != 0)
-        {
-          udbg("ERROR: Failed to re-schedule keyboard poll: %d\n", ret);
-        }
-
-      /* If USB debug is on, then provide some periodic indication that
-       * polling is still happening.
-       */
-
-#ifdef CONFIG_DEBUG_USB
-      npolls++;
-#endif
-    }
-  irqrestore(flags);
-
-  /* If USB debug is on, then provide some periodic indication that
-   * polling is still happening.
-   */
-
-#ifdef CONFIG_DEBUG_USB
-  if (!priv->disconnected && (npolls & ~31) == 0)
-   {
-      udbg("Still polling: %d\n", npolls);
-   }
-#endif
+  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
 }
 
 /****************************************************************************
@@ -477,9 +413,8 @@ static void usbhost_kbdpoll(FAR void *arg)
  *
  ****************************************************************************/
 
-static void usbhost_destroy(FAR void *arg)
+static void usbhost_destroy(FAR struct usbhost_state_s *priv)
 {
-  FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)arg;
   char devname[DEV_NAMELEN];
 
   DEBUGASSERT(priv != NULL);
@@ -528,6 +463,191 @@ static void usbhost_destroy(FAR void *arg)
   usbhost_freeclass(priv);
 }
 
+/****************************************************************************
+ * Name: usbhost_dumprpt
+ *
+ * Description:
+ *   Dump the interesting context of the keyboard report that we just
+ *   received.
+ *
+ * Input Parameters:
+ *   arg - A reference to the class instance to be destroyed.
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_VERBOSE)
+static inline void usbhost_dumprpt(uint8_t *buffer)
+{
+  struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)buffer;
+  int i;
+  for (i = 0; i < 6; i++)
+    {
+      if (rpt->key[i])
+        {
+          uvdbg("Key %d: %08x modifier: %08x\n", rpt->key[i], rpt->modifier);
+        }
+    }
+}
+#else
+#  define usbhost_dumprpt(buffer)
+#endif
+
+/****************************************************************************
+ * Name: usbhost_kbdpoll
+ *
+ * Description:
+ *   Periodically check for new keyboard data.
+ *
+ * Input Parameters:
+ *   arg - A reference to the class instance to be destroyed.
+ *
+ * Returned Values:
+ *   None
+ *
+ ****************************************************************************/
+
+static int usbhost_kbdpoll(int argc, char *argv[])
+{
+  FAR struct usbhost_state_s *priv;
+  FAR struct usb_ctrlreq_s   *ctrlreq;
+#ifdef CONFIG_DEBUG_USB
+  static unsigned int         npolls = 0;
+#endif
+  static unsigned int         nerrors;
+  int                         ret;
+
+  uvdbg("Started\n");
+
+  /* Synchronize with the start-up logic.  Get the private instance, re-start
+   * the start-up logic, and wait a bit to make sure that all of the class
+   * creation logic has a chance to run to completion.
+   *
+   * NOTE: that the reference count is incremented here.  Therefore, we know
+   * that the driver data structure will remain stable while this thread is
+   * running.
+   */
+
+   priv = g_priv;
+   DEBUGASSERT(priv != NULL);
+ 
+   priv->polling = true;
+   priv->crefs++;
+   usbhost_givesem(&g_syncsem);
+   sleep(1);
+  
+  /* Loop here until the device is disconnected */
+
+  uvdbg("Entering poll loop\n");
+  while (!priv->disconnected)
+    {
+      /* Make sure that we have exclusive access to the private data
+       * structure. There may now be other tasks with the character driver
+       * open and actively trying to interact with the class driver.
+       */
+
+      usbhost_takesem(&priv->exclsem);
+
+      /* Format the hid report request:
+       *
+       *   bmRequestType 10000001
+       *   bRequest      GET_DESCRIPTOR (0x06)
+       *   wValue        Descriptor Type and Descriptor Index
+       *   wIndex        Interface Number
+       *   wLength       Descriptor Length
+       *   Data          Descriptor Data
+       */
+
+      ctrlreq       = (struct usb_ctrlreq_s *)priv->tbuffer;
+      ctrlreq->type = USB_REQ_DIR_IN|USB_REQ_RECIPIENT_INTERFACE;
+      ctrlreq->req  = USB_REQ_GETDESCRIPTOR;
+      usbhost_putle16(ctrlreq->value, (USBHID_DESCTYPE_REPORT << 8));
+      usbhost_putle16(ctrlreq->index, 0);
+      usbhost_putle16(ctrlreq->len, 8);
+
+      /* Send the report */
+
+      ret = DRVR_CTRLIN(priv->drvr, ctrlreq, priv->tbuffer);
+      usbhost_givesem(&priv->exclsem);
+
+      if (ret != OK)
+        {
+          nerrors++;
+          udbg("ERROR: GETDESCRIPTOR/REPORT, DRVR_CTRLIN returned: %d/%d\n",
+               ret, nerrors);
+
+          if (nerrors > 200)
+            {
+              udbg("Too man errors... aborting: %d\n", nerrors);
+              break;
+            }
+        }
+      else
+        {
+          /* If debug is enabled, then dump the interesting poarts of the
+           * report that we just received.
+           */
+
+          usbhost_dumprpt(priv->tbuffer);
+
+          /* Add the newly recevied keystrokes to our internal buffer */
+#warning "Missing logic"
+        }
+
+      /* If USB debug is on, then provide some periodic indication that
+       * polling is still happening.
+       */
+
+#ifdef CONFIG_DEBUG_USB
+      npolls++;
+      if (!(npolls & ~31) == 0)
+        {
+          udbg("Still polling: %d\n", npolls);
+        }
+#endif
+      /* Wait for the required amount (or until a signal is received).  We
+       * will wake up when either the delay elapses or we are signalled that
+       * the device has been disconnected.
+       */
+
+      usleep(CONFIG_HIDKBD_POLLUSEC);
+    }
+
+  /* We get here when the driver is removed.. or when too many errors have
+   * been encountered.
+   *
+   * Make sure that we have exclusive access to the private data structure.
+   * There may now be other tasks with the character driver open and actively
+   * trying to interact with the class driver.
+   */
+
+  usbhost_takesem(&priv->exclsem);
+
+  /* Indicate that we are no longer running and decrement the reference
+   * count help by this thread.  If there are no other users of the class,
+   * we can destroy it now.  Otherwise, we have to wait until the all
+   * of the file descriptors are closed.
+   */
+ 
+  udbg("Keyboard removed, polling halted\n");
+  priv->polling = false;
+  if (--priv->crefs < 2)
+    {
+      /* Destroy the instance (while we hold the semaphore!) */
+ 
+      usbhost_destroy(priv);
+    }
+  else
+    {
+      /* No, we will destroy the driver instance when it is finally closed */
+
+      usbhost_givesem(&priv->exclsem);
+    }
+  return 0;
+}
+
 /****************************************************************************
  * Name: usbhost_cfgdesc
  *
@@ -769,6 +889,7 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
 static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 {
+  char devname[DEV_NAMELEN];
   int ret;
 
   /* Set aside a transfer buffer for exclusive use by the keyboard class driver */
@@ -787,63 +908,63 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
   priv->crefs++;
   DEBUGASSERT(priv->crefs == 2);
 
-  /* Setup a period worker thread event to poll the USB device. */
-
-  ret = work_queue(&priv->work, usbhost_kbdpoll, priv, CONFIG_HIDKBD_POLLTICKS);
-  
-  /* Register the driver */
-
-  if (ret == OK)
-    {
-      char devname[DEV_NAMELEN];
-
-      uvdbg("Register driver\n");
-      usbhost_mkdevname(priv, devname);
-      (void)register_driver(devname, &usbhost_fops, 0666, NULL);
-    }
-
-  /* Check if we successfully initialized. We now have to be concerned
-   * about asynchronous modification of crefs because the driver has
-   * been registerd.
+  /* Start a worker task to poll the USB device.  It would be nice to used the
+   * the NuttX worker thread to do this, but this task needs to wait for events
+   * and activities on the worker thread should not involve significant waiting.
+   * Having a dedicated thread is more efficient in this sense, but requires more
+   * memory resources, primarily for the dedicated stack (CONFIG_HIDKBD_STACKSIZE).
    */
 
-  if (ret == OK)
+  uvdbg("user_start: Start poll task\n");
+
+  /* The inputs to a task started by task_create() are very awkard for this
+   * purpose.  They are really designed for command line tasks (argc/argv). So
+   * the following is kludge pass binary data when the keyboard poll task
+   * is started.
+   *
+   * First, make sure we have exclusive access to g_priv (what is the likelihood
+   * of this being used?  About zero, but we protect it anyway).
+   */
+
+  usbhost_takesem(&g_exclsem);
+  g_priv = priv;
+
+#ifndef CONFIG_CUSTOM_STACK
+  priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
+                              CONFIG_HIDKBD_STACKSIZE,
+                              (main_t)usbhost_kbdpoll, (const char **)NULL);
+#else
+  priv->pollpid = task_create("usbhost", CONFIG_HIDKBD_DEFPRIO,
+                              (main_t)hidkbd_waiter, (const char **)NULL);
+#endif
+  if (priv->pollpid == ERROR)
     {
-      usbhost_takesem(&priv->exclsem);
-      DEBUGASSERT(priv->crefs >= 2);
+      /* Failed to started the poll thread... probably due to memory resources */
 
-      /* Handle a corner case where (1) open() has been called so the
-       * reference count is > 2, but the device has been disconnected.
-       * In this case, the class instance needs to persist until close()
-       * is called.
-       */
-
-      if (priv->crefs <= 2 && priv->disconnected)
-        {
-          /* We don't have to give the semaphore because it will be
-           * destroyed when usb_destroy is called.
-           */
-  
-          ret = -ENODEV;
-        }
-      else
-        {
-          /* Ready for normal operation as a character device driver */
-
-          uvdbg("Successfully initialized\n");
-          priv->crefs--;
-          usbhost_givesem(&priv->exclsem);
-        }
+      usbhost_givesem(&g_exclsem);
+      ret = -ENOMEM;
+      goto errout;
     }
 
-  /* Disconnect on any errors detected during volume initialization */
+  /* Now wait for the poll task to get properly initialized */
 
-  if (ret != OK)
-    {
-      udbg("ERROR! Aborting: %d\n", ret);
-      usbhost_destroy(priv);
-    }
+  usbhost_takesem(&g_syncsem);
+  usbhost_givesem(&g_exclsem);
 
+  /* Register the driver */
+
+  uvdbg("Register driver\n");
+  usbhost_mkdevname(priv, devname);
+  ret = register_driver(devname, &usbhost_fops, 0666, NULL);
+
+  /* We now have to be concerned about asynchronous modification of crefs
+   * because the driver has been registerd.
+   */
+
+errout:
+  usbhost_takesem(&priv->exclsem);
+  priv->crefs--;
+  usbhost_givesem(&priv->exclsem);
   return ret;
 }
 
@@ -936,7 +1057,7 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
  * Name: usbhost_tdalloc
  *
  * Description:
- *   Allocate transfer descriptor memory.
+ *   Allocate transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -949,15 +1070,15 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
 
 static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
 {
-  DEBUGASSERT(priv && priv->tdbuffer == NULL);
-  return DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen);
+  DEBUGASSERT(priv && priv->tbuffer == NULL);
+  return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen);
 }
 
 /****************************************************************************
  * Name: usbhost_tdfree
  *
  * Description:
- *   Free transfer descriptor memory.
+ *   Free transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -973,12 +1094,12 @@ static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
   int result = OK;
   DEBUGASSERT(priv);
 
-  if (priv->tdbuffer)
+  if (priv->tbuffer)
     {
       DEBUGASSERT(priv->drvr);
-      result         = DRVR_FREE(priv->drvr, priv->tdbuffer);
-      priv->tdbuffer = NULL;
-      priv->tdbuflen = 0;
+      result         = DRVR_FREE(priv->drvr, priv->tbuffer);
+      priv->tbuffer = NULL;
+      priv->tbuflen = 0;
     }
   return result;
 }
@@ -1049,9 +1170,7 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d
 
           priv->drvr               = drvr;
 
-          /* NOTE: We do not yet know the geometry of the USB mass storage device */
- 
-          /* Return the instance of the USB mass storage class */
+          /* Return the instance of the USB keyboard class driver */
  
           return &priv->class;
         }
@@ -1123,6 +1242,34 @@ static int usbhost_connect(FAR struct usbhost_class_s *class,
         }
     }
  
+  /* Disconnect on any errors detected during initialization. */
+
+  if (ret != OK)
+    {
+      priv->disconnected = true;
+
+      /* Is the polling task still running?  If so, then ask it politely to
+       * stop and release its reference count.
+       */
+ 
+      while (priv->polling)
+        {
+          (void)kill(priv->pollpid, SIGALRM);
+          usleep(500*1000);
+        }
+
+      /* The following operations when crefs == 1 are safe because we know
+       * that there is no outstanding open references to the driver.
+       */
+
+      if (priv->crefs <= 1)
+        {
+          /* Destroy the class instance */
+
+          usbhost_destroy(priv);
+        }
+    }
+
   return ret;
 }
 
@@ -1151,61 +1298,134 @@ static int usbhost_connect(FAR struct usbhost_class_s *class,
 static int usbhost_disconnected(struct usbhost_class_s *class)
 {
   FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class;
-  irqstate_t flags;
 
   DEBUGASSERT(priv != NULL);
 
-  /* Set an indication to any users of the mass storage device that the device
+  /* Set an indication to any users of the keyboard device that the device
    * is no longer available.
    */
 
-  flags              = irqsave();
   priv->disconnected = true;
+  ullvdbg("Disconnected\n");
 
-  /* Now check the number of references on the class instance.  If it is one,
-   * then we can free the class instance now.  Otherwise, we will have to
-   * wait until the holders of the references free them by closing the
-   * driver.
+  /* Signal the keyboard polling task.  When that task wakes up, it will
+   * decrement the reference count and, perhaps, destroy the class instance.
    */
 
-  ullvdbg("crefs: %d\n", priv->crefs);
-  if (priv->crefs == 1)
-    {
-      /* Destroy the class instance.  If we are executing from an interrupt
-       * handler, then defer the destruction to the worker thread.
-       * Otherwise, destroy the instance now.
-       */
-
-      if (up_interrupt_context())
-        {
-          /* Destroy the instance on the worker thread. */
-
-          uvdbg("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy);
-
-          /* Cancel the period polling thread */
-
-          (void)work_cancel(&priv->work);
-          DEBUGASSERT(priv->work.worker == NULL);
-
-          /* Then schedule the destruction */
-
-          (void)work_queue(&priv->work, usbhost_destroy, priv, 0);
-       }
-      else
-        {
-          /* Do the work now */
-
-          usbhost_destroy(priv);
-        }
-    }
-
-  irqrestore(flags);  
+  (void)kill(priv->pollpid, SIGALRM);
   return OK;
 }
 
 /****************************************************************************
  * Character driver methods
  ****************************************************************************/
+/****************************************************************************
+ * Name: usbhost_open
+ *
+ * Description:
+ *   Standard character driver open method.
+ *
+ ****************************************************************************/
+
+static int usbhost_open(FAR struct file *filep)
+{
+  FAR struct inode           *inode;
+  FAR struct usbhost_state_s *priv;
+  irqstate_t flags;
+  int ret;
+
+  uvdbg("Entry\n");
+  DEBUGASSERT(filep && filep->f_inode);
+  inode = filep->f_inode;
+  priv  = inode->i_private;
+
+  /* Make sure that we have exclusive access to the private data structure */
+
+  DEBUGASSERT(priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
+  usbhost_takesem(&priv->exclsem);
+
+  /* Check if the keyboard device is still connected.  We need to disable
+   * interrupts momentarily to assure that there are no asynchronous disconnect
+   * events.
+   */
+
+  flags = irqsave();
+  if (priv->disconnected)
+    {
+      /* No... the driver is no longer bound to the class.  That means that
+       * the USB storage device is no longer connected.  Refuse any further
+       * attempts to open the driver.
+       */
+
+      ret = -ENODEV;
+    }
+  else
+    {
+      /* Otherwise, just increment the reference count on the driver */
+
+      priv->crefs++;
+      ret = OK;
+    }
+  irqrestore(flags);
+
+  usbhost_givesem(&priv->exclsem);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: usbhost_close
+ *
+ * Description:
+ *   Standard character driver close method.
+ *
+ ****************************************************************************/
+
+static int usbhost_close(FAR struct file *filep)
+{
+  FAR struct inode           *inode;
+  FAR struct usbhost_state_s *priv;
+  irqstate_t flags;
+
+  uvdbg("Entry\n");
+  DEBUGASSERT(filep && filep->f_inode);
+  inode = filep->f_inode;
+  priv  = inode->i_private;
+
+  /* Decrement the reference count on the driver */
+
+  DEBUGASSERT(priv->crefs > 1);
+  usbhost_takesem(&priv->exclsem);
+  priv->crefs--;
+
+  /* Release the semaphore.  The following operations when crefs == 1 are
+   * safe because we know that there is no outstanding open references to
+   * the driver.
+   */
+
+  usbhost_givesem(&priv->exclsem);
+
+  /* We need to disable interrupts momentarily to assure that there are
+   * no asynchronous disconnect events.
+   */
+
+  flags = irqsave();
+
+  /* Check if the USB keyboard device is still connected.  If the device is
+   * not connected and the reference count just decremented to one, then
+   * unregister then free the driver class instance.
+   */
+
+  if (priv->crefs <= 1 && priv->disconnected)
+    {
+      /* Destroy the class instance */
+
+      usbhost_destroy(priv);
+    }
+
+  irqrestore(flags);
+  return OK;
+}
+
 /****************************************************************************
  * Name: usbhost_read
  *
@@ -1214,8 +1434,45 @@ static int usbhost_disconnected(struct usbhost_class_s *class)
  *
  ****************************************************************************/
 
-static ssize_t usbhost_read(FAR struct file *filp, FAR char *buffer, size_t len)
+static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len)
 {
+  FAR struct inode           *inode;
+  FAR struct usbhost_state_s *priv;
+  irqstate_t flags;
+  int ret;
+
+  uvdbg("Entry\n");
+  DEBUGASSERT(filep && filep->f_inode && buffer);
+  inode = filep->f_inode;
+  priv  = inode->i_private;
+
+  /* Make sure that we have exclusive access to the private data structure */
+
+  DEBUGASSERT(priv && priv->crefs > 0 && priv->crefs < USBHOST_MAX_CREFS);
+  usbhost_takesem(&priv->exclsem);
+
+  /* Check if the keyboard is still connected.  We need to disable interrupts
+   * momentarily to assure that there are no asynchronous disconnect events.
+   */
+
+  flags = irqsave();
+  if (priv->disconnected)
+    {
+      /* No... the driver is no longer bound to the class.  That means that
+       * the USB keybaord is no longer connected.  Refuse any further attempts
+       * to access the driver.
+       */
+
+      ret = -ENODEV;
+    }
+  else
+    {
+      /* Read data from our internal buffer of received characters */
+#warning "Missing logic"
+    }
+  irqrestore(flags);
+
+  usbhost_givesem(&priv->exclsem);
   return 0; /* Return EOF for now */
 }
 
@@ -1227,9 +1484,11 @@ static ssize_t usbhost_read(FAR struct file *filp, FAR char *buffer, size_t len)
  *
  ****************************************************************************/
 
-static ssize_t usbhost_write(FAR struct file *filp, FAR const char *buffer, size_t len)
+static ssize_t usbhost_write(FAR struct file *filep, FAR const char *buffer, size_t len)
 {
-  return len; /* Say that everything was written for now */
+  /* We won't try to write to the keyboard */
+
+  return -ENOSYS;
 }
 
 /****************************************************************************
@@ -1241,7 +1500,7 @@ static ssize_t usbhost_write(FAR struct file *filp, FAR const char *buffer, size
  ****************************************************************************/
 
 #ifndef CONFIG_DISABLE_POLL
-static int usbhost_poll(FAR struct file *filp, FAR struct pollfd *fds,
+static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
                         bool setup)
 {
   if (setup)
@@ -1281,6 +1540,9 @@ int usbhost_kbdinit(void)
 {
   /* Perform any one-time initialization of the class implementation */
 
+  sem_init(&g_exclsem, 0, 1);
+  sem_init(&g_syncsem, 0, 0);
+
   /* Advertise our availability to support (certain) devices */
 
   return usbhost_registerclass(&g_skeleton);
diff --git a/drivers/usbhost/usbhost_skeleton.c b/drivers/usbhost/usbhost_skeleton.c
index fe3d71a28d..ae37da02a4 100644
--- a/drivers/usbhost/usbhost_skeleton.c
+++ b/drivers/usbhost/usbhost_skeleton.c
@@ -65,12 +65,12 @@
 #endif
 
 /* Driver support ***********************************************************/
-/* This format is used to construct the /dev/sd[n] device driver path.  It
+/* This format is used to construct the /dev/skel[n] device driver path.  It
  * defined here so that it will be used consistently in all places.
  */
 
-#define DEV_FORMAT          "/dev/sd%c"
-#define DEV_NAMELEN         10
+#define DEV_FORMAT          "/dev/skel%c"
+#define DEV_NAMELEN         12
 
 /* Used in usbhost_cfgdesc() */
 
@@ -85,8 +85,8 @@
  * Private Types
  ****************************************************************************/
 
-/* This structure contains the internal, private state of the USB host mass
- * storage class.
+/* This structure contains the internal, private state of the USB host class
+ * driver.
  */
 
 struct usbhost_state_s
@@ -99,15 +99,15 @@ struct usbhost_state_s
 
   struct usbhost_driver_s *drvr;
 
-  /* The remainder of the fields are provide o the mass storage class */
+  /* The remainder of the fields are provide to the class driver */
   
-  char                    sdchar;       /* Character identifying the /dev/sd[n] device */
+  char                    devchar;       /* Character identifying the /dev/skel[n] device */
   volatile bool           disconnected; /* TRUE: Device has been disconnected */
   int16_t                 crefs;        /* Reference count on the driver instance */
   sem_t                   exclsem;      /* Used to maintain mutual exclusive access */
   struct work_s           work;         /* For interacting with the worker thread */
-  FAR uint8_t            *tdbuffer;     /* The allocated transfer descriptor buffer */
-  size_t                  tdbuflen;     /* Size of the allocated transfer buffer */
+  FAR uint8_t            *tbuffer;      /* The allocated transfer buffer */
+  size_t                  tbuflen;      /* Size of the allocated transfer buffer */
   usbhost_ep_t            epin;         /* IN endpoint */
   usbhost_ep_t            epout;        /* OUT endpoint */
 };
@@ -152,8 +152,8 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val);
 
 /* Transfer descriptor memory management */
 
-static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv);
-static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv);
+static inline int usbhost_talloc(FAR struct usbhost_state_s *priv);
+static inline int usbhost_tfree(FAR struct usbhost_state_s *priv);
 
 /* struct usbhost_registry_s methods */
  
@@ -174,8 +174,7 @@ static int usbhost_disconnected(FAR struct usbhost_class_s *class);
  ****************************************************************************/
 
 /* This structure provides the registry entry ID informatino that will  be 
- * used to associate the USB host mass storage class to a connected USB
- * device.
+ * used to associate the USB class driver to a connected USB device.
  */
 
 static const const struct usbhost_id_s g_id =
@@ -197,7 +196,7 @@ static struct usbhost_registry_s g_skeleton =
   &g_id                   /* id[]     */
 };
 
-/* This is a bitmap that is used to allocate device names /dev/sda-z. */
+/* This is a bitmap that is used to allocate device names /dev/skela-z. */
 
 static uint32_t g_devinuse;
 
@@ -303,7 +302,7 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
       if ((g_devinuse & bitno) == 0)
         {
           g_devinuse |= bitno;
-          priv->sdchar = 'a' + devno;
+          priv->devchar = 'a' + devno;
           irqrestore(flags);
           return OK;
         }
@@ -315,7 +314,7 @@ static int usbhost_allocdevno(FAR struct usbhost_state_s *priv)
 
 static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
 {
-  int devno = 'a' - priv->sdchar;
+  int devno = 'a' - priv->devchar;
 
   if (devno >= 0 && devno < 26)
     {
@@ -327,7 +326,7 @@ static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
 
 static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname)
 {
-  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->sdchar);
+  (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
 }
 
 /****************************************************************************
@@ -761,10 +760,10 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
 }
 
 /****************************************************************************
- * Name: usbhost_tdalloc
+ * Name: usbhost_talloc
  *
  * Description:
- *   Allocate transfer descriptor memory.
+ *   Allocate transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -775,17 +774,17 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
+static inline int usbhost_talloc(FAR struct usbhost_state_s *priv)
 {
-  DEBUGASSERT(priv && priv->tdbuffer == NULL);
-  return DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen);
+  DEBUGASSERT(priv && priv->tbuffer == NULL);
+  return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen);
 }
 
 /****************************************************************************
- * Name: usbhost_tdfree
+ * Name: usbhost_tfree
  *
  * Description:
- *   Free transfer descriptor memory.
+ *   Free transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -796,17 +795,17 @@ static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
+static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
 {
   int result = OK;
   DEBUGASSERT(priv);
 
-  if (priv->tdbuffer)
+  if (priv->tbuffer)
     {
       DEBUGASSERT(priv->drvr);
-      result         = DRVR_FREE(priv->drvr, priv->tdbuffer);
-      priv->tdbuffer = NULL;
-      priv->tdbuflen = 0;
+      result         = DRVR_FREE(priv->drvr, priv->tbuffer);
+      priv->tbuffer = NULL;
+      priv->tbuflen = 0;
     }
   return result;
 }
@@ -877,9 +876,7 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d
 
           priv->drvr               = drvr;
 
-          /* NOTE: We do not yet know the geometry of the USB mass storage device */
- 
-          /* Return the instance of the USB mass storage class */
+          /* Return the instance of the USB class driver */
  
           return &priv->class;
         }
@@ -983,8 +980,8 @@ static int usbhost_disconnected(struct usbhost_class_s *class)
 
   DEBUGASSERT(priv != NULL);
 
-  /* Set an indication to any users of the mass storage device that the device
-   * is no longer available.
+  /* Set an indication to any users of the device that the device is no
+   * longer available.
    */
 
   flags              = irqsave();
diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c
index 759d5bd6c7..e6fd110476 100644
--- a/drivers/usbhost/usbhost_storage.c
+++ b/drivers/usbhost/usbhost_storage.c
@@ -121,7 +121,7 @@ struct usbhost_state_s
 
   struct usbhost_driver_s *drvr;
 
-  /* The remainder of the fields are provide o the mass storage class */
+  /* The remainder of the fields are provide to the mass storage class */
   
   char                    sdchar;       /* Character identifying the /dev/sd[n] device */
   volatile bool           disconnected; /* TRUE: Device has been disconnected */
@@ -130,8 +130,8 @@ struct usbhost_state_s
   uint32_t                nblocks;      /* Number of blocks on the USB mass storage device */
   sem_t                   exclsem;      /* Used to maintain mutual exclusive access */
   struct work_s           work;         /* For interacting with the worker thread */
-  FAR uint8_t            *tdbuffer;     /* The allocated transfer descriptor buffer */
-  size_t                  tdbuflen;     /* Size of the allocated transfer buffer */
+  FAR uint8_t            *tbuffer;      /* The allocated transfer buffer */
+  size_t                  tbuflen;      /* Size of the allocated transfer buffer */
   usbhost_ep_t            bulkin;       /* Bulk IN endpoint */
   usbhost_ep_t            bulkout;      /* Bulk OUT endpoint */
 };
@@ -210,8 +210,8 @@ static void usbhost_putbe32(uint8_t *dest, uint32_t val);
 
 /* Transfer descriptor memory management */
 
-static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv);
-static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv);
+static inline int usbhost_talloc(FAR struct usbhost_state_s *priv);
+static inline int usbhost_tfree(FAR struct usbhost_state_s *priv);
 static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *priv);
 
 /* struct usbhost_registry_s methods */
@@ -665,8 +665,8 @@ usbhost_writecbw(size_t startsector, uint16_t blocksize,
 
 static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv)
 {
-  FAR struct usb_ctrlreq_s *req = (FAR struct usb_ctrlreq_s *)priv->tdbuffer;
-  DEBUGASSERT(priv && priv->tdbuffer);
+  FAR struct usb_ctrlreq_s *req = (FAR struct usb_ctrlreq_s *)priv->tbuffer;
+  DEBUGASSERT(priv && priv->tbuffer);
 
   /* Request maximum logical unit number.  NOTE: On an IN transaction, The
    * req and buffer pointers passed to DRVR_CTRLIN may refer to the same
@@ -678,7 +678,7 @@ static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv)
   req->type    = USB_DIR_IN|USB_REQ_TYPE_CLASS|USB_REQ_RECIPIENT_INTERFACE;
   req->req     = USBSTRG_REQ_GETMAXLUN;
   usbhost_putle16(req->len, 1);
-  return DRVR_CTRLIN(priv->drvr, req, priv->tdbuffer);
+  return DRVR_CTRLIN(priv->drvr, req, priv->tbuffer);
 }
 
 static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
@@ -705,10 +705,10 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
       /* Receive the CSW */
 
       result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                             priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                             priv->tbuffer, USBSTRG_CSW_SIZEOF);
       if (result == OK)
         {
-          usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tdbuffer);
+          usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tbuffer);
         }
     }
   return result;
@@ -738,16 +738,16 @@ static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv)
       /* Receive the sense data response */
 
       result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                             priv->tdbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF);
+                             priv->tbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF);
       if (result == OK)
         {
           /* Receive the CSW */
 
           result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                                 priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                                 priv->tbuffer, USBSTRG_CSW_SIZEOF);
           if (result == OK)
             {
-              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tdbuffer);
+              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tbuffer);
             }
         }
     }
@@ -780,22 +780,22 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
       /* Receive the read capacity CBW IN response */
 
       result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                             priv->tdbuffer, SCSIRESP_READCAPACITY10_SIZEOF);
+                             priv->tbuffer, SCSIRESP_READCAPACITY10_SIZEOF);
       if (result == OK)
         {
           /* Save the capacity information */
 
-          resp            = (FAR struct scsiresp_readcapacity10_s *)priv->tdbuffer;
+          resp            = (FAR struct scsiresp_readcapacity10_s *)priv->tbuffer;
           priv->nblocks   = usbhost_getbe32(resp->lba);
           priv->blocksize = usbhost_getbe32(resp->blklen);
 
           /* Receive the CSW */
 
           result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                                 priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                                 priv->tbuffer, USBSTRG_CSW_SIZEOF);
           if (result == OK)
             {
-              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tdbuffer);
+              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tbuffer);
             }
         }
     }
@@ -828,20 +828,20 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv)
       /* Receive the CBW IN response */
 
       result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                             priv->tdbuffer, SCSIRESP_INQUIRY_SIZEOF);
+                             priv->tbuffer, SCSIRESP_INQUIRY_SIZEOF);
       if (result == OK)
         {
           /* TODO: If USB debug is enabled, dump the response data here */
 
-          resp = (FAR struct scsiresp_inquiry_s *)priv->tdbuffer;
+          resp = (FAR struct scsiresp_inquiry_s *)priv->tbuffer;
 
           /* Receive the CSW */
 
           result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                                 priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                                 priv->tbuffer, USBSTRG_CSW_SIZEOF);
           if (result == OK)
             {
-              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tdbuffer);
+              usbhost_dumpcsw((FAR struct usbstrg_csw_s *)priv->tbuffer);
             }
         }
     }
@@ -896,7 +896,7 @@ static void usbhost_destroy(FAR void *arg)
 
   /* Free any transfer buffers */
 
-  usbhost_tdfree(priv);
+  usbhost_tfree(priv);
 
   /* Destroy the semaphores */
 
@@ -1153,7 +1153,7 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
 
   /* Set aside a transfer buffer for exclusive use by the mass storage driver */
 
-  ret = usbhost_tdalloc(priv);
+  ret = usbhost_talloc(priv);
   if (ret != OK)
     {
       udbg("ERROR: Failed to allocate transfer buffer\n");
@@ -1185,7 +1185,7 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
         {
           /* Is the unit is ready */
 
-          csw = (FAR struct usbstrg_csw_s *)priv->tdbuffer;
+          csw = (FAR struct usbstrg_csw_s *)priv->tbuffer;
           if (csw->status == 0)
             {
               /* Yes... break out of the loop */
@@ -1221,7 +1221,7 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
         {
           /* Check the CSW for errors */
 
-          csw = (FAR struct usbstrg_csw_s *)priv->tdbuffer;
+          csw = (FAR struct usbstrg_csw_s *)priv->tbuffer;
           if (csw->status != 0)
             {
               udbg("ERROR: CSW status error: %d\n", csw->status);
@@ -1242,7 +1242,7 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
         {
           /* Check the CSW for errors */
 
-          csw = (FAR struct usbstrg_csw_s *)priv->tdbuffer;
+          csw = (FAR struct usbstrg_csw_s *)priv->tbuffer;
           if (csw->status != 0)
             {
               udbg("ERROR: CSW status error: %d\n", csw->status);
@@ -1478,10 +1478,10 @@ static void usbhost_putbe32(uint8_t *dest, uint32_t val)
 }
 
 /****************************************************************************
- * Name: usbhost_tdalloc
+ * Name: usbhost_talloc
  *
  * Description:
- *   Allocate transfer descriptor memory.
+ *   Allocate transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -1492,17 +1492,17 @@ static void usbhost_putbe32(uint8_t *dest, uint32_t val)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
+static inline int usbhost_talloc(FAR struct usbhost_state_s *priv)
 {
-  DEBUGASSERT(priv && priv->tdbuffer == NULL);
-  return DRVR_ALLOC(priv->drvr, &priv->tdbuffer, &priv->tdbuflen);
+  DEBUGASSERT(priv && priv->tbuffer == NULL);
+  return DRVR_ALLOC(priv->drvr, &priv->tbuffer, &priv->tbuflen);
 }
 
 /****************************************************************************
- * Name: usbhost_tdfree
+ * Name: usbhost_tfree
  *
  * Description:
- *   Free transfer descriptor memory.
+ *   Free transfer buffer memory.
  *
  * Input Parameters:
  *   priv - A reference to the class instance.
@@ -1513,17 +1513,17 @@ static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
+static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
 {
   int result = OK;
   DEBUGASSERT(priv);
 
-  if (priv->tdbuffer)
+  if (priv->tbuffer)
     {
       DEBUGASSERT(priv->drvr);
-      result         = DRVR_FREE(priv->drvr, priv->tdbuffer);
-      priv->tdbuffer = NULL;
-      priv->tdbuflen = 0;
+      result         = DRVR_FREE(priv->drvr, priv->tbuffer);
+      priv->tbuffer = NULL;
+      priv->tbuflen = 0;
     }
   return result;
 }
@@ -1547,11 +1547,11 @@ static FAR struct usbstrg_cbw_s *usbhost_cbwalloc(FAR struct usbhost_state_s *pr
 {
   FAR struct usbstrg_cbw_s *cbw = NULL;
 
-  DEBUGASSERT(priv->tdbuffer && priv->tdbuflen >= sizeof(struct usbstrg_cbw_s))
+  DEBUGASSERT(priv->tbuffer && priv->tbuflen >= sizeof(struct usbstrg_cbw_s))
 
   /* Intialize the CBW sructure */
 
-  cbw = (FAR struct usbstrg_cbw_s *)priv->tdbuffer;
+  cbw = (FAR struct usbstrg_cbw_s *)priv->tbuffer;
   memset(cbw, 0, sizeof(struct usbstrg_cbw_s));
   usbhost_putle32(cbw->signature, USBSTRG_CBW_SIGNATURE);
   return cbw;
@@ -1943,14 +1943,14 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
                   /* Receive the CSW */
 
                   result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                                         priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                                         priv->tbuffer, USBSTRG_CSW_SIZEOF);
                   if (result == OK)
                     {
                       FAR struct usbstrg_csw_s *csw;
 
                       /* Check the CSW status */
 
-                      csw = (FAR struct usbstrg_csw_s *)priv->tdbuffer;
+                      csw = (FAR struct usbstrg_csw_s *)priv->tbuffer;
                       if (csw->status == 0)
                         {
                           ret = nsectors;
@@ -2035,14 +2035,14 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
                   /* Receive the CSW */
 
                   result = DRVR_TRANSFER(priv->drvr, priv->bulkin,
-                                         priv->tdbuffer, USBSTRG_CSW_SIZEOF);
+                                         priv->tbuffer, USBSTRG_CSW_SIZEOF);
                   if (result == OK)
                     {
                       FAR struct usbstrg_csw_s *csw;
 
                       /* Check the CSW status */
 
-                      csw = (FAR struct usbstrg_csw_s *)priv->tdbuffer;
+                      csw = (FAR struct usbstrg_csw_s *)priv->tbuffer;
                       if (csw->status == 0)
                         {
                           ret = nsectors;
diff --git a/examples/hidkbd/hidkbd_main.c b/examples/hidkbd/hidkbd_main.c
index 8a98afd518..47de0fbcf2 100644
--- a/examples/hidkbd/hidkbd_main.c
+++ b/examples/hidkbd/hidkbd_main.c
@@ -150,7 +150,7 @@ int user_start(int argc, char *argv[])
   /* First, register all of the USB host HID keyboard class driver */
 
   printf("user_start: Register class drivers\n");
-  ret = usbhost_storageinit();
+  ret = usbhost_kbdinit();
   if (ret != OK)
     {
       printf("user_start: Failed to register the KBD class\n");