From 857a6111bcc1c47ca5eb96fbf171332e9d7fbbc5 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Mon, 20 Dec 2010 20:59:12 +0000
Subject: [PATCH] Add a little more

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3201 42af7a65-404d-4744-a932-0658087f49c3
---
 arch/arm/src/lpc17xx/lpc17_ohciram.h |  23 +-
 arch/arm/src/lpc17xx/lpc17_usbhost.c | 383 ++++++++++++++++++++++++---
 include/nuttx/usb/usbhost.h          |  14 +-
 3 files changed, 372 insertions(+), 48 deletions(-)

diff --git a/arch/arm/src/lpc17xx/lpc17_ohciram.h b/arch/arm/src/lpc17xx/lpc17_ohciram.h
index 431a8d8d32..5607e35d6e 100755
--- a/arch/arm/src/lpc17xx/lpc17_ohciram.h
+++ b/arch/arm/src/lpc17xx/lpc17_ohciram.h
@@ -144,7 +144,12 @@
 #if CONFIG_USBHOST_TDBUFFERS > 0 && !defined(CONFIG_USBHOST_TDBUFSIZE)
 #  define CONFIG_USBHOST_TDBUFSIZE 128
 #endif
-#define LPC17_TDBUFFER_SIZE (CONFIG_USBHOST_TDBUFFERS * CONFIG_USBHOST_TDBUFSIZE)
+
+#if (CONFIG_USBHOST_TDBUFSIZE & 3) != 0
+#  error "TD buffer size must be an even number of 32-bit words"
+#endif
+
+#define LPC17_TDFREE_SIZE (CONFIG_USBHOST_TDBUFFERS * CONFIG_USBHOST_TDBUFSIZE)
 
 /* Configurable size of an IO buffer.  The number of IO buffers will be determined
  * by what is left at the end of the BANK1 memory setup aside of OHCI RAM.
@@ -154,6 +159,10 @@
 #  define CONFIG_USBHOST_IOBUFSIZE 512
 #endif
 
+#if (CONFIG_USBHOST_IOBUFSIZE & 3) != 0
+#  error "IO buffer size must be an even number of 32-bit words"
+#endif
+
 /* OHCI Memory Layout ***************************************************************/
 /* Example:
  *  Hardware:
@@ -171,8 +180,8 @@
  *  Sizes of things
  *    CONFIG_USBHOST_NEDS         2
  *    LPC17_EDFREE_SIZE           48
- *    LPC17_TDBUFFER_SIZE         128
- *    LPC17_TDBUFFER_SIZE         512
+ *    LPC17_TDFREE_SIZE           128
+ *    LPC17_IOFREE_SIZE           512
  *
  *  Memory Layout
  *    LPC17_OHCIRAM_END          (0x20008000 + 16384) = 0x2000c000
@@ -186,8 +195,8 @@
  *    LPC17_TDTAIL_ADDR           0x2000bd10
  *    LPC17_EDCTRL_ADDR           0x2000bd20
  *    LPC17_EDFREE_BASE           0x2000bd30
- *    LPC17_TDBUFFER_BASE         0x2000bd50
- *    LPC17_IOBUFFER_BASE         0x2000bdd0
+ *    LPC17_TDFREE_BASE           0x2000bd50
+ *    LPC17_IOFREE_BASE           0x2000bdd0
  *    LPC17_IOBUFFERS            (0x2000c000 + 0x2000bdd0) / 512 = 560/512 = 1
  *
  *  Wasted memory:                560-512 = 48 bytes
@@ -198,8 +207,8 @@
 #define LPC17_TDTAIL_ADDR   (LPC17_TDHEAD_ADDR + LPC17_TD_SIZE)
 #define LPC17_EDCTRL_ADDR   (LPC17_TDTAIL_ADDR + LPC17_TD_SIZE)
 #define LPC17_EDFREE_BASE   (LPC17_EDCTRL_ADDR + LPC17_ED_SIZE)
-#define LPC17_TDBUFFER_BASE (LPC17_EDFREE_BASE + LPC17_EDFREE_SIZE)
-#define LPC17_IOBUFFER_BASE (LPC17_TDBUFFER_BASE + LPC17_TDBUFFER_SIZE)
+#define LPC17_TDFREE_BASE   (LPC17_EDFREE_BASE + LPC17_EDFREE_SIZE)
+#define LPC17_IOFREE_BASE   (LPC17_TDFREE_BASE + LPC17_TDFREE_SIZE)
 
 /* Finally, use the remainder of the allocated OHCI for IO buffers */
 
diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c
index c2cb49f574..d2bc45dde4 100755
--- a/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -104,7 +104,7 @@
 #define EDCTRL      ((volatile struct lpc17_hced_s *)LPC17_EDCTRL_ADDR)
 
 #define EDFREE      ((struct lpc17_hced_s *)LPC17_EDFREE_BASE)
-#define TDBuffer    ((volatile uint8_t *)(LPC17_TDBUFFER_BASE)
+#define TDFREE      ((uint8_t *)LPC17_TDFREE_BASE)
 
 /* Descriptors *****************************************************************/
 
@@ -141,8 +141,10 @@ struct lpc17_usbhost_s
 
   /* Driver status */
 
-  uint8_t tdstatus;  /* TD control status bits from last Writeback Done Head event */
-  sem_t   wdhsem;    /* Semaphore  used to wait for Writeback Done Head event */
+  volatile uint8_t tdstatus;  /* TD control status bits from last Writeback Done Head event */
+  volatile bool    connected; /* Connected to device */
+  sem_t            rhssem;    /* Semaphore  to wait Root Hub Status change */
+  sem_t            wdhsem;    /* Semaphore  used to wait for Writeback Done Head event */
 };
 
 /* Host Controller Communication Area */
@@ -176,7 +178,7 @@ struct lpc17_hced_s
   volatile  uint32_t  next;            /* Physical address of next Endpoint descriptor */
 };
 
-/* The following is used manage a list of free EDs */
+/* The following are used to manage lists of free EDs and TD buffers*/
 
 struct lpc17_edlist_s
 {
@@ -184,6 +186,12 @@ struct lpc17_edlist_s
   uint32_t               pad[3];       /* To make the same size as struct lpc17_hced_s */
 };
 
+struct lpc17_tdlist_s
+{
+  struct lpc17_tdlist_s *flink;        /* Link to next TD buffer in the list */
+                                       /* Variable length buffer data follows */
+};
+
 /*******************************************************************************
  * Private Function Prototypes
  *******************************************************************************/
@@ -217,6 +225,8 @@ static void lpc17_edfree(struct lpc17_usbhost_s *priv, struct lpc17_hced_s *ed);
 static void lpc17_enqueuetd(volatile struct lpc17_hced_s *ed, uint32_t dirpid,
                             uint32_t toggle, volatile uint8_t *buffer,
                             size_t buflen);
+static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
+                        uint8_t *buffer, size_t buflen);
 
 /* Class helper functions ******************************************************/
 
@@ -277,9 +287,10 @@ static struct lpc17_usbhost_s g_usbhost =
   .class          = NULL,
 };
 
-/* This is a free list of EDs */
+/* This is a free list of EDs and TD buffers */
 
 static struct lpc17_edlist_s *g_edfree;
+static struct lpc17_tdlist_s *g_tdfree;
 
 /*******************************************************************************
  * Public Data
@@ -418,7 +429,7 @@ static void lpc17_putreg(uint32_t val, uint32_t addr)
  *   This is just a wrapper to handle the annoying behavior of semaphore
  *   waits that return due to the receipt of a signal.
  *
- ****************************************************************************/
+ *******************************************************************************/
 
 static void lpc17_takesem(sem_t *sem)
 {
@@ -440,7 +451,7 @@ static void lpc17_takesem(sem_t *sem)
  * Description:
  *   Get a (possibly unaligned) 16-bit little endian value.
  *
- ****************************************************************************/
+ *******************************************************************************/
 
 static inline uint16_t lpc17_getle16(const uint8_t *val)
 {
@@ -453,7 +464,7 @@ static inline uint16_t lpc17_getle16(const uint8_t *val)
  * Description:
  *   Put a (possibly unaligned) 16-bit little endian value.
  *
- ****************************************************************************/
+ *******************************************************************************/
 
 static void lpc17_putle16(uint8_t *dest, uint16_t val)
 {
@@ -494,6 +505,39 @@ static void lpc17_edfree(struct lpc17_usbhost_s *priv, struct lpc17_hced_s *ed)
   g_edfree                      = edfree;
 }
 
+/*******************************************************************************
+ * Name: lpc17_tdalloc
+ *
+ * Description:
+ *   Allocate an TD buffer from the free list
+ *
+ *******************************************************************************/
+
+static uint8_t *lpc17_tdalloc(struct lpc17_usbhost_s *priv)
+{
+  uint8_t *ret = (uint8_t *)g_tdfree;
+  if (ret)
+    {
+      g_tdfree = ((struct lpc17_tdlist_s*)ret)->flink;
+    }
+  return ret;
+}
+
+/*******************************************************************************
+ * Name: lpc17_tdfree
+ *
+ * Description:
+ *   Return an TD buffer to the free list
+ *
+ *******************************************************************************/
+
+static void lpc17_tdfree(struct lpc17_usbhost_s *priv, uint8_t *buffer)
+{
+  struct lpc17_tdlist_s *tdfree = (struct lpc17_tdlist_s *)buffer;
+  tdfree->flink                 = g_tdfree;
+  g_tdfree                      = tdfree;
+}
+
 /*******************************************************************************
  * Name: lpc17_enqueuetd
  *
@@ -519,14 +563,73 @@ static void lpc17_enqueuetd(volatile struct lpc17_hced_s *ed, uint32_t dirpid,
   ed->next        = 0;
 }
 
-/****************************************************************************
- * Name: lpc17_classbind
+/*******************************************************************************
+ * Name: lpc17_configdesc
+ *
+ * Description:
+ *   Process a IN or OUT request on the control endpoint.  This function
+ *   will enqueue the request and wait for it to complete.  Only one transfer
+ *   may be queued; Neither these methods nor the transfer() method can be
+ *   called again until the control transfer functions returns.
+ *
+ *   These are blocking methods; these functions will not return until the
+ *   control transfer has completed.
+ *
+ *******************************************************************************/
+
+static int lpc17_ctrltd(struct lpc17_usbhost_s *priv, uint32_t dirpid,
+                        uint8_t *buffer, size_t buflen)
+{
+  uint32_t toggle;
+  uint32_t regval;
+
+  if (dirpid == GTD_STATUS_DP_SETUP)
+    {
+      toggle = GTD_STATUS_T_DATA0;
+    }
+  else
+    {
+      toggle = GTD_STATUS_T_DATA1;
+    }
+
+  /* Then enqueue the transfer */
+
+  lpc17_enqueuetd(EDCTRL, dirpid, toggle, buffer, buflen);
+
+  lpc17_putreg(LPC17_EDCTRL_ADDR, LPC17_USBHOST_CTRLHEADED);
+
+  regval = lpc17_getreg(LPC17_USBHOST_CMDST);
+  regval |= OHCI_CMDST_CLF;
+  lpc17_putreg(regval, LPC17_USBHOST_CMDST);
+      
+  regval = lpc17_getreg(LPC17_USBHOST_CTRL);
+  regval |= OHCI_CTRL_CLE;
+  lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+
+  /* Wait for the Writeback Done Head interrupt */
+
+  lpc17_takesem(&priv->wdhsem);
+
+  /* Check the TDHEAD completion status bits */
+
+  if (priv->tdstatus == 0)
+    {
+      return OK;
+    }
+  else 
+    {
+      return -EIO;
+    }
+}
+
+/*******************************************************************************
+ * Name: lpc17_configdesc
  *
  * Description:
  *   A configuration descriptor has been obtained from the device.  Find the
  *   ID information for the class that supports this device.
  *
- ****************************************************************************/
+ *******************************************************************************/
 
 static inline int
 lpc17_configdesc(struct lpc17_usbhost_s *priv, const uint8_t *configdesc,
@@ -591,14 +694,14 @@ lpc17_configdesc(struct lpc17_usbhost_s *priv, const uint8_t *configdesc,
   return -ENOENT;
 }
 
-/****************************************************************************
+/*******************************************************************************
  * Name: lpc17_classbind
  *
  * Description:
  *   A configuration descriptor has been obtained from the device.  Try to
  *   bind this configuration descriptor with a supported class.
  *
- ****************************************************************************/
+ *******************************************************************************/
 
 static int lpc17_classbind(struct lpc17_usbhost_s *priv,
                            const uint8_t *configdesc, int desclen)
@@ -664,7 +767,114 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
   /* Read the device interrupt status register */
 
   usbtrace(TRACE_INTENTRY(LPC17_TRACEINTID_USB), 0xbeef);
-#warning "Not implemented"
+  uint32_t intstatus;
+  uint32_t intenable;
+
+  /* Read Interrupt Status and mask out interrupts that are not enabled. */
+
+  intstatus  = lpc17_getreg(LPC17_USBHOST_INTST);
+  intenable  = lpc17_getreg(LPC17_USBHOST_INTEN);
+  intstatus &= intenable;
+
+  if (intstatus != 0)
+    {
+      /* Root hub status change interrupt */
+
+      if ((intstatus & OHCI_INT_RHSC) != 0)
+        {
+          uint32_t rhportst1 = lpc17_getreg(LPC17_USBHOST_RHPORTST1);
+          ullvdbg("Root Hub Status Change, RHPORTST: %08x\n", portstatus);
+
+          if ((rhportst1 & OHCI_RHPORTST_CSC) != 0)
+            {
+              uint32_t rhstatus = lpc17_getreg(LPC17_USBHOST_RHSTATUS);
+              ullvdbg("Connect Status Change, RHSTATUS: %08x\n", portstatus);
+
+              /* If DRWE is set, Connect Status Change indicates a remote wake-up event */
+
+              if (rhstatus & OHCI_RHSTATUS_DRWE)
+                {
+                  ullvdbg("DRWE: Remote wake-up\n");
+                }
+
+              /* Otherwise... Not a remote wake-up event */
+
+              else
+                {
+                  /* Check if we are not connected */
+
+                  if ((rhportst1 & OHCI_RHPORTST_CCS) != 0)
+                    {
+                      if (!priv->connected)
+                        {
+                          DEBUGASSERT(priv->rhssem.semcount <= 0);
+                          priv->tdstatus = 0;
+                          priv->connected = true;
+                          lpc17_givesem(&priv->rhssem);
+                        }
+                      else
+                        {
+                          ulldbg("Spurious status change (connected)\n");
+                        }
+                    }
+
+                  /* Check if we are now disconnected */
+ 
+                  else if (priv->connected)
+                    {
+                      /* Yes.. disable interrupts */
+
+                      lpc17_putreg(0, LPC17_USBHOST_INTEN);
+                      priv->connected = false;
+
+                      /* Are we bound to a class instance? */
+
+                      if (priv->class)
+                        {
+                          /* Yes.. Disconnect the class */
+
+                          CLASS_DISCONNECTED(priv->class);
+                        }
+                    }
+                  else
+                    {
+                       ulldbg("Spurious status change (disconnected)\n");
+                    }
+                }
+
+              /* Clear the CSC interrupt */
+
+              lpc17_putreg(OHCI_RHPORTST_CSC, LPC17_USBHOST_RHPORTST1);
+            }
+
+          /* Check for port reset status change */
+
+          if ((rhportst1 & OHCI_RHPORTST_PRSC) != 0)
+            {
+              /* Release the RH port from reset */
+
+              lpc17_putreg(OHCI_RHPORTST_PRSC, LPC17_USBHOST_RHPORTST1);
+            }
+        }
+
+      /* Writeback Done Head interrupt */
+ 
+      if ((intstatus & OHCI_INT_WDH) != 0)
+        {
+          /* Get the condition code from the control word */
+
+          priv->tdstatus = (TDHEAD->ctrl & GTD_STATUS_CC_MASK) >> GTD_STATUS_CC_SHIFT;
+
+          /* And wake up the thread waiting for the WDH event */
+
+          DEBUGASSERT(priv->wdhsem.semcount <= 0);
+          lpc17_givesem(&priv->wdhsem);
+        }
+
+      /* Clear interrupt status register */
+
+      lpc17_putreg(intstatus, LPC17_USBHOST_INTST);
+    }
   usbtrace(TRACE_INTEXIT(LPC17_TRACEINTID_USB), 0);
   return OK;
 }
@@ -673,7 +883,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
  * USB Host Controller Operations
  *******************************************************************************/
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_enumerate
  *
  * Description:
@@ -698,7 +908,7 @@ static int lpc17_usbinterrupt(int irq, FAR void *context)
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
 static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
 {
@@ -706,7 +916,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
   return -ENOSYS;
 }
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_alloc
  *
  * Description:
@@ -730,7 +940,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
  static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
                         FAR uint8_t **buffer, FAR size_t *maxlen)
@@ -739,7 +949,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
   return -ENOSYS;
 }
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_free
  *
  * Description:
@@ -760,7 +970,7 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr)
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
 static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
 {
@@ -768,12 +978,12 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
   return -ENOSYS;
 }
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_ctrlin and lpc17_ctrlout
  *
  * Description:
  *   Process a IN or OUT request on the control endpoint.  These methods
- *   will enqueue the request and return immediately.  Only one transfer may be
+ *   will enqueue the request and wait for it to complete.  Only one transfer may be
  *   queued; Neither these methods nor the transfer() method can be called again
  *   until the control transfer functions returns.
  *
@@ -797,25 +1007,59 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
 static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr,
                         FAR const struct usb_ctrlreq_s *req,
                         FAR uint8_t *buffer)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  uint16_t len;
+  int  ret;
+
+  len = lpc17_getle16(req->len);
+  ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
+  if (ret == OK)
+    {
+      if (len)
+        {
+          ret = lpc17_ctrltd(priv, GTD_STATUS_DP_IN, buffer, len);
+        }
+
+      if (ret == OK)
+        {
+          ret = lpc17_ctrltd(priv, GTD_STATUS_DP_OUT, NULL, 0);
+        }
+    }
+  return ret;
 }
 
 static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
                          FAR const struct usb_ctrlreq_s *req,
                          FAR const uint8_t *buffer)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  uint16_t len;
+  int  ret;
+
+  len = lpc17_getle16(req->len);
+  ret = lpc17_ctrltd(priv, GTD_STATUS_DP_SETUP, (uint8_t*)req, USB_SIZEOF_CTRLREQ);
+  if (ret == OK)
+    {
+      if (len)
+        {
+          ret = lpc17_ctrltd(priv, GTD_STATUS_DP_OUT, (uint8_t*)buffer, len);
+        }
+
+      if (ret == OK)
+        {
+          ret = lpc17_ctrltd(priv, GTD_STATUS_DP_IN, NULL, 0);
+        }
+    }
+  return ret;
 }
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_transfer
  *
  * Description:
@@ -843,17 +1087,75 @@ static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
 static int lpc17_transfer(FAR struct usbhost_driver_s *drvr,
-                          FAR struct usbhost_epdesc_s *ed,
+                          FAR struct usbhost_epdesc_s *ep,
                           FAR uint8_t *buffer, size_t buflen)
 {
-# warning "Not Implemented"
-  return -ENOSYS;
+  struct lpc17_usbhost_s *priv = (struct lpc17_usbhost_s *)drvr;
+  struct lpc17_hced_s *ed;
+  uint32_t dirpid;
+  uint32_t regval;
+  int ret = -ENOMEM;
+
+  /* Allocate an ED */
+
+  ed = lpc17_edalloc(priv);
+  if (ed)
+    {
+      /* Format the endpoint descriptor */
+ 
+      lpc17_edinit(ed);
+      ed->ctrl = (uint32_t)(ep->addr) << ED_CONTROL_EN_SHIFT |
+                 (uint32_t)(ep->mxpacketsize) << ED_CONTROL_MPS_SHIFT;
+
+      /* Get the direction of the endpoint */
+
+      if (ep->in)
+        {
+          ed->ctrl |= ED_CONTROL_D_IN;
+          dirpid    = GTD_STATUS_DP_IN;
+        }
+      else
+        {
+          ed->ctrl |= ED_CONTROL_D_OUT;
+          dirpid    = GTD_STATUS_DP_OUT;
+        }
+
+      /* Then enqueue the transfer */
+
+      lpc17_enqueuetd(ed, dirpid, GTD_STATUS_T_TOGGLE, buffer, buflen);
+
+      lpc17_putreg((uint32_t)ed, LPC17_USBHOST_BULKHEADED);
+
+      regval = lpc17_getreg(LPC17_USBHOST_CMDST);
+      regval |= OHCI_CMDST_BLF;
+      lpc17_putreg(regval, LPC17_USBHOST_CMDST);
+      
+      regval = lpc17_getreg(LPC17_USBHOST_CTRL);
+      regval |= OHCI_CTRL_BLE;
+      lpc17_putreg(regval, LPC17_USBHOST_CTRL);
+
+      /* Wait for the Writeback Done Head interrupt */
+
+      lpc17_takesem(&priv->wdhsem);
+
+      /* Check the TDHEAD completion status bits */
+
+      if (priv->tdstatus == 0)
+        {
+          ret = OK;
+        }
+      else 
+        {
+          ret = -EIO;
+        }
+    }
+  return ret;
 }
 
-/************************************************************************************
+/*******************************************************************************
  * Name: lpc17_disconnect
  *
  * Description:
@@ -873,7 +1175,7 @@ static int lpc17_transfer(FAR struct usbhost_driver_s *drvr,
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ *******************************************************************************/
 
 static void lpc17_disconnect(FAR struct usbhost_driver_s *drvr)
 {
@@ -933,6 +1235,7 @@ void up_usbhostinitialize(void)
 {
   struct lpc17_usbhost_s *priv = &g_usbhost;
   uint32_t regval;
+  uint8_t *tdfree;
   irqstate_t flags;
   int i;
 
@@ -940,6 +1243,7 @@ void up_usbhostinitialize(void)
 
   /* Initialize the state data structure */
 
+  sem_init(&priv->rhssem, 0, 0);
   sem_init(&priv->wdhsem, 0, 0);
 
   /* Enable power by setting PCUSB in the PCONP register */
@@ -995,6 +1299,17 @@ void up_usbhostinitialize(void)
       lpc17_edfree(priv, &EDFREE[i]);
     }
 
+  /* Initialize user-configurable TD buffers */
+
+  tdfree = TDFREE;
+  for (i = 0; i < CONFIG_USBHOST_NEDS; i++)
+    {
+      /* Put the TD buffer in a free list */
+
+      lpc17_tdfree(priv, tdfree);
+      tdfree += CONFIG_USBHOST_TDBUFSIZE;
+    }
+
   /* Wait 50MS then perform hardware reset */
 
   up_mdelay(50);
diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h
index 687dd884b9..a4aee9e162 100644
--- a/include/nuttx/usb/usbhost.h
+++ b/include/nuttx/usb/usbhost.h
@@ -227,7 +227,7 @@
  *
  * Description:
  *   Process a IN or OUT request on the control endpoint.  These methods
- *   will enqueue the request and return immediately.  Only one transfer may be
+ *   will enqueue the request and wait for it to complete.  Only one transfer may be
  *   queued; Neither these methods nor the transfer() method can be called again
  *   until the control transfer functions returns.
  *
@@ -261,8 +261,8 @@
  *
  * Description:
  *   Process a request to handle a transfer descriptor.  This method will
- *   enqueue the transfer request and return immediately.  Only one transfer may be
- *   queued; Neither this method nor the ctrlin or ctrlout methods can be called
+ *   enqueue the transfer request and rwait for it to complete.  Only one transfer may
+ *   be queued; Neither this method nor the ctrlin or ctrlout methods can be called
  *   again until this function returns.
  *
  *   This is a blocking method; this functions will not return until the
@@ -414,8 +414,8 @@ struct usbhost_driver_s
   int (*free)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
 
   /* Process a IN or OUT request on the control endpoint.  These methods
-   * will enqueue the request and return immediately.  Only one transfer may be
-   * queued; Neither these methods nor the transfer() method can be called again
+   * will enqueue the request and wait for it to complete.  Only one transfer may
+   * be queued; Neither these methods nor the transfer() method can be called again
    * until the control transfer functions returns.
    *
    * These are blocking methods; these functions will not return until the
@@ -430,8 +430,8 @@ struct usbhost_driver_s
                  FAR const uint8_t *buffer);
 
   /* Process a request to handle a transfer descriptor.  This method will
-   * enqueue the transfer request and return immediately.  Only one transfer may be
-   * queued; Neither this method nor the ctrlin or ctrlout methods can be called
+   * enqueue the transfer request and wait for it to complete.  Only one transfer may
+   * be queued; Neither this method nor the ctrlin or ctrlout methods can be called
    * again until this function returns.
    *
    * This is a blocking method; this functions will not return until the
-- 
GitLab