From 4566137cb8f4a2a5f240e9b93eb6a52e369b5d11 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Mon, 20 Dec 2010 16:51:15 +0000
Subject: [PATCH] minor

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3200 42af7a65-404d-4744-a932-0658087f49c3
---
 arch/arm/src/lpc17xx/lpc17_usbhost.c | 123 ++++++++++++++++++++++-----
 drivers/usbhost/usbhost_storage.c    | 117 +------------------------
 include/nuttx/usb/usbhost.h          | 103 +++++++++-------------
 3 files changed, 143 insertions(+), 200 deletions(-)

diff --git a/arch/arm/src/lpc17xx/lpc17_usbhost.c b/arch/arm/src/lpc17xx/lpc17_usbhost.c
index 8fb4d1df39..c2cb49f574 100755
--- a/arch/arm/src/lpc17xx/lpc17_usbhost.c
+++ b/arch/arm/src/lpc17xx/lpc17_usbhost.c
@@ -44,6 +44,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdlib.h>
+#include <semaphore.h>
 #include <string.h>
 #include <errno.h>
 #include <debug.h>
@@ -137,6 +138,11 @@ struct lpc17_usbhost_s
   /* The bound device class driver */
 
   struct usbhost_class_s *class;
+
+  /* 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 */
 };
 
 /* Host Controller Communication Area */
@@ -194,6 +200,16 @@ static void lpc17_putreg(uint32_t val, uint32_t addr);
 # define lpc17_putreg(val,addr) putreg32(val,addr)
 #endif
 
+/* Semaphores ******************************************************************/
+
+static void lpc17_takesem(sem_t *sem);
+#define lpc17_givesem(s) sem_post(s);
+
+/* Byte stream access helper functions *****************************************/
+
+static inline uint16_t lpc17_getle16(const uint8_t *val);
+static void lpc17_putle16(uint8_t *dest, uint16_t val);
+
 /* Descriptor helper functions *************************************************/
 
 static struct lpc17_hced_s *lpc17_edalloc(struct lpc17_usbhost_s *priv);
@@ -220,8 +236,12 @@ static int lpc17_enumerate(FAR struct usbhost_driver_s *drvr);
 static int lpc17_alloc(FAR struct usbhost_driver_s *drvr,
                          FAR uint8_t **buffer, FAR size_t *maxlen);
 static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
-static int lpc17_control(FAR struct usbhost_driver_s *drvr,
-                           const struct usb_ctrlreq_s *req, FAR uint8_t *buffer);
+static int lpc17_ctrlin(FAR struct usbhost_driver_s *drvr,
+                        FAR const struct usb_ctrlreq_s *req,
+                        FAR uint8_t *buffer);
+static int lpc17_ctrlout(FAR struct usbhost_driver_s *drvr,
+                         FAR const struct usb_ctrlreq_s *req,
+                         FAR const uint8_t *buffer);
 static int lpc17_transfer(FAR struct usbhost_driver_s *drvr,
                             FAR struct usbhost_epdesc_s *ed,
                             FAR uint8_t *buffer, size_t buflen);
@@ -249,7 +269,8 @@ static struct lpc17_usbhost_s g_usbhost =
       .enumerate  = lpc17_enumerate,
       .alloc      = lpc17_alloc,
       .free       = lpc17_free,
-      .control    = lpc17_control,
+      .ctrlin     = lpc17_ctrlin,
+      .ctrlout    = lpc17_ctrlout,
       .transfer   = lpc17_transfer,
       .disconnect = lpc17_disconnect,
     },
@@ -390,6 +411,56 @@ static void lpc17_putreg(uint32_t val, uint32_t addr)
 }
 #endif
 
+/****************************************************************************
+ * Name: lpc17_takesem
+ *
+ * Description:
+ *   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)
+{
+  /* Take the semaphore (perhaps waiting) */
+
+  while (sem_wait(sem) != 0)
+    {
+      /* The only case that an error should occr here is if the wait was
+       * awakened by a signal.
+       */
+
+      ASSERT(errno == EINTR);
+    }
+}
+
+/****************************************************************************
+ * Name: lpc17_getle16
+ *
+ * Description:
+ *   Get a (possibly unaligned) 16-bit little endian value.
+ *
+ ****************************************************************************/
+
+static inline uint16_t lpc17_getle16(const uint8_t *val)
+{
+  return (uint16_t)val[1] << 8 | (uint16_t)val[0];
+}
+
+/****************************************************************************
+ * Name: lpc17_putle16
+ *
+ * Description:
+ *   Put a (possibly unaligned) 16-bit little endian value.
+ *
+ ****************************************************************************/
+
+static void lpc17_putle16(uint8_t *dest, uint16_t val)
+{
+  dest[0] = val & 0xff; /* Little endian means LS byte first in byte stream */
+  dest[1] = val >> 8;
+}
+
 /*******************************************************************************
  * Name: lpc17_edalloc
  *
@@ -698,15 +769,16 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
 }
 
 /************************************************************************************
- * Name: lpc17_control
+ * Name: lpc17_ctrlin and lpc17_ctrlout
  *
  * Description:
- *   Enqueue a request on the control endpoint.  This method will enqueue
- *   the request and return immediately.  The transfer will be performed
- *   asynchronously.  When the transfer completes, the USB host driver will
- *   call the complete() method of the struct usbhost_class_s interface.
- *   Only one transfer may be queued; Neither this method nor the transfer()
- *   method can be called again until the class complete() method has been called.
+ *   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
+ *   until the control transfer functions returns.
+ *
+ *   These are blocking methods; these functions will not return until the
+ *   control transfer has completed.
  *
  * Input Parameters:
  *   drvr - The USB host driver instance obtained as a parameter from the call to
@@ -727,8 +799,17 @@ static int lpc17_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
  *
  ************************************************************************************/
 
-static int lpc17_control(FAR struct usbhost_driver_s *drvr,
-                         const struct usb_ctrlreq_s *req, FAR uint8_t *buffer)
+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;
+}
+
+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;
@@ -738,13 +819,13 @@ static int lpc17_control(FAR struct usbhost_driver_s *drvr,
  * Name: lpc17_transfer
  *
  * Description:
- *   Enqueue a request to handle a transfer descriptor.  This method will
- *   enqueue the transfer request and return immediately.  The transfer will
- *   be performed asynchronously.  When the transfer completes, the USB host
- *   driver will call the complete() method of the struct usbhost_class_s
- *   interface.  Only one transfer may be queued; Neither this method nor the
- *   control method can be called again until the class complete() method has
- *   been called.
+ *   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
+ *   again until this function returns.
+ *
+ *   This is a blocking method; this functions will not return until the
+ *   transfer has completed.
  *
  * Input Parameters:
  *   drvr - The USB host driver instance obtained as a parameter from the call to
@@ -857,6 +938,10 @@ void up_usbhostinitialize(void)
 
   usbtrace(TRACE_DEVINIT, 0);
 
+  /* Initialize the state data structure */
+
+  sem_init(&priv->wdhsem, 0, 0);
+
   /* Enable power by setting PCUSB in the PCONP register */
 
   flags   = irqsave();
diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c
index 2193caf1f0..149a8a7aff 100644
--- a/drivers/usbhost/usbhost_storage.c
+++ b/drivers/usbhost/usbhost_storage.c
@@ -124,7 +124,6 @@ struct usbhost_state_s
   uint16_t                blocksize;  /* Block size of USB mass storage device */
   uint32_t                nblocks;    /* Number of blocks on the USB mass storage device */
   sem_t                   exclsem;    /* Used to maintain mutual exclusive access */
-  sem_t                   waitsem;    /* Used to wait for transfer completion events */
   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 */
@@ -203,8 +202,6 @@ static struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *drvr,
 
 static int usbhost_configdesc(FAR struct usbhost_class_s *class,
                               FAR const uint8_t *configdesc, int desclen);
-static int usbhost_complete(FAR struct usbhost_class_s *class,
-                            FAR const uint8_t *response, int resplen);
 static int usbhost_disconnected(FAR struct usbhost_class_s *class);
 
 /* struct block_operations methods */
@@ -596,13 +593,7 @@ static inline int usbhost_maxlunreq(FAR struct usbhost_state_s *priv)
       req.req     = USBSTRG_REQ_GETMAXLUN;
       usbhost_putle16(req.len, 1);
 
-      result      = DRVR_CONTROL(priv->drvr, &req, priv->tdbuffer);
-      if (result == OK)
-        {
-          /* Wait for the control operation to complete */
-
-          usbhost_takesem(&priv->waitsem);
-        }
+      result      = DRVR_CTRLIN(priv->drvr, &req, priv->tdbuffer);
     }
   return result;
 }
@@ -624,18 +615,10 @@ static inline int usbhost_testunitready(FAR struct usbhost_state_s *priv)
                             (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
       if (result == OK)
         {
-          /* Wait for the CBW OUT operation to complete */
-
-          usbhost_takesem(&priv->waitsem);
-
           /* Receive the CSW */
 
           result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                  priv->tdbuffer, USBSTRG_CSW_SIZEOF);
-
-          /* Wait for the CSW IN operation to complete */
-
-          usbhost_takesem(&priv->waitsem); 
         }
     }
   return result;
@@ -658,30 +641,16 @@ static inline int usbhost_requestsense(FAR struct usbhost_state_s *priv)
                             (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
       if (result == OK)
         {
-          /* Wait for the CBW OUT operation to complete */
-
-          usbhost_takesem(&priv->waitsem);
-
           /* Receive the sense data response */
 
           result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                  priv->tdbuffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF);
           if (result == OK)
             {
-              /* Wait for the CBW IN response operation to complete */
-
-              usbhost_takesem(&priv->waitsem);
-
               /* Receive the CSW */
 
               result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                      priv->tdbuffer, USBSTRG_CSW_SIZEOF);
-              if (result == OK)
-                {
-                  /* Wait for the CSW IN operation to complete */
-
-                  usbhost_takesem(&priv->waitsem); 
-                }
             }
         }
     }
@@ -706,20 +675,12 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
                              (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
       if (result == OK)
         {
-          /* Wait for the CBW OUT operation to complete */
-
-          usbhost_takesem(&priv->waitsem);
-
           /* Receive the read capacity CBW IN response */
 
           result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                  priv->tdbuffer, SCSIRESP_READCAPACITY10_SIZEOF);
           if (result == OK)
             {
-              /* Wait for the CBW IN response operation to complete */
-
-              usbhost_takesem(&priv->waitsem);
-
               /* Save the capacity information */
 
               resp = (FAR struct scsiresp_readcapacity10_s *)priv->tdbuffer;
@@ -730,12 +691,6 @@ static inline int usbhost_readcapacity(FAR struct usbhost_state_s *priv)
 
               result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                      priv->tdbuffer, USBSTRG_CSW_SIZEOF);
-              if (result == OK)
-                {
-                  /* Wait for the CSW IN operation to complete */
-
-                  usbhost_takesem(&priv->waitsem); 
-                }
             }
         }
     }
@@ -760,20 +715,12 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv)
                              (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
       if (result == OK)
         {
-          /* Wait for the CBW OUT operation to complete */
-
-          usbhost_takesem(&priv->waitsem);
-
           /* Receive the CBW IN response */
 
           result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                  priv->tdbuffer, SCSIRESP_INQUIRY_SIZEOF);
           if (result == OK)
             {
-              /* Wait for the CBW IN response operation to complete */
-
-              usbhost_takesem(&priv->waitsem);
-
               /* TODO: If USB debug is enabled, dump the response data here */
 
               resp = (FAR struct scsiresp_inquiry_s *)priv->tdbuffer;
@@ -782,10 +729,6 @@ static inline int usbhost_inquiry(FAR struct usbhost_state_s *priv)
 
               result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                      priv->tdbuffer, USBSTRG_CSW_SIZEOF);
-
-              /* Wait for the CSW IN operation to complete */
-
-              usbhost_takesem(&priv->waitsem); 
             }
         }
     }
@@ -831,7 +774,6 @@ static void usbhost_destroy(FAR void *arg)
   /* Destroy the semaphores */
 
   sem_destroy(&priv->exclsem);
-  sem_destroy(&priv->waitsem);
 
   /* And free the class instance.  Hmmm.. this may execute on the worker
    * thread and the work structure is part of what is getting freed.
@@ -1308,7 +1250,6 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d
          /* Initialize class method function pointers */
 
           priv->class.configdesc   = usbhost_configdesc;
-          priv->class.complete     = usbhost_complete;
           priv->class.disconnected = usbhost_disconnected;
 
           /* The initial reference count is 1... One reference is held by the driver */
@@ -1318,7 +1259,6 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_driver_s *d
           /* Initialize semphores (this works okay in the interrupt context) */
 
           sem_init(&priv->exclsem, 0, 1);
-          sem_init(&priv->waitsem, 0, 0);
 
           /* Bind the driver to the storage class instance */
 
@@ -1509,45 +1449,6 @@ static int usbhost_configdesc(FAR struct usbhost_class_s *class,
   return OK;
 }
 
-/****************************************************************************
- * Name: usbhost_complete
- *
- * Description:
- *   This function implements the complete() method of struct
- *   usbhost_class_s.  In the interface with the USB host drivers, the class
- *   will queue USB IN/OUT transactions.  The enqueuing function will return
- *   and the transactions will be performed asynchrounously.  When the
- *   transaction completes, the USB host driver will call this function in
- *   order to inform the class that the transaction has completed and to
- *   provide any response data.
- *
- * Input Parameters:
- *   class - The USB host class entry previously obtained from a call to
- *     create().
- *   response - Response data buffer
- *   resplen - Number of bytes of data in the response data buffer.
- *
- * Returned Values:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
- *
- * Assumptions:
- *   This function may be called from an interrupt handler.
- *
- ****************************************************************************/
-
-static int usbhost_complete(FAR struct usbhost_class_s *class,
-                            FAR const uint8_t *response, int resplen)
-{
-  FAR struct usbhost_state_s *priv = (FAR struct usbhost_state_s *)class;
-  DEBUGASSERT(priv != NULL && priv->waitsem.semcount <= 0);
-
-  /* Wake up the application thread waiting for the transfer completion event */
-
-  usbhost_givesem(&priv->waitsem);
-  return OK;
-}
-
 /****************************************************************************
  * Name: usbhost_disconnected
  *
@@ -1743,20 +1644,12 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
                                  (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
           if (result == OK)
             {
-              /* Wait for the CBW OUT operation to complete */
-
-              usbhost_takesem(&priv->waitsem);
-
               /* Receive the user data */
 #warning "For lpc17xx, I think this buffer needs to lie in BANK1"
               result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
                                      buffer, priv->blocksize * nsectors);
               if (result == OK)
                 {
-                  /* Wait for the data in operation to complete */
-
-                  usbhost_takesem(&priv->waitsem);
-
                   /* Receive the CSW */
 
                   result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
@@ -1843,20 +1736,12 @@ static ssize_t usbhost_write(FAR struct inode *inode, const unsigned char *buffe
                                  (uint8_t*)cbw, USBSTRG_CBW_SIZEOF);
           if (result == OK)
             {
-              /* Wait for the CBW OUT operation to complete */
-
-              usbhost_takesem(&priv->waitsem);
-
               /* Send the user data */
 #warning "For lpc17xx, I think this buffer needs to lie in BANK1"
               result = DRVR_TRANSFER(priv->drvr, &priv->bulkout,
                                      (uint8_t*)buffer, priv->blocksize * nsectors);
               if (result == OK)
                 {
-                  /* Wait for the data in operation to complete */
-
-                  usbhost_takesem(&priv->waitsem);
-
                   /* Receive the CSW */
 
                   result = DRVR_TRANSFER(priv->drvr, &priv->bulkin,
diff --git a/include/nuttx/usb/usbhost.h b/include/nuttx/usb/usbhost.h
index 2035299c28..687dd884b9 100644
--- a/include/nuttx/usb/usbhost.h
+++ b/include/nuttx/usb/usbhost.h
@@ -118,33 +118,6 @@
 
 #define CLASS_CONFIGDESC(class,configdesc,desclen) ((class)->configdesc(class,configdesc,desclen))
 
-/************************************************************************************
- * Name: CLASS_COMPLETE
- *
- * Description:
- *   This macro will call the complete() method of struct usbhost_class_s.  In the
- *   interface with the USB host drivers, the class will queue USB IN/OUT
- *   transactions.  The enqueuing function will return and the transactions will be
- *   performed asynchrounously.  When the transaction completes, the USB host driver
- *   will call this function in order to inform the class that the transaction has
- *   completed and to provide any response data.
- *
- * Input Parameters:
- *   class - The USB host class entry previously obtained from a call to create().
- *   response - Response data buffer
- *   resplen - Number of bytes of data in the response data buffer.
- *
- * Returned Values:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
- *
- * Assumptions:
- *   This function may be called from an interrupt handler.
- *
- ************************************************************************************/
-
-#define CLASS_COMPLETE(class,response,resplen) (class)->complete(class,response,resplen))
-
 /************************************************************************************
  * Name: CLASS_DISCONNECTED
  *
@@ -250,15 +223,16 @@
 #define DRVR_FREE(drvr,buffer) ((drvr)->free(drvr,buffer))
 
 /************************************************************************************
- * Name: DRVR_CONTROL
+ * Name: DRVR_CTRLIN and DRVR_CTRLOUT
  *
  * Description:
- *   Enqueue a request on the control endpoint.  This method will enqueue
- *   the request and return immediately.  The transfer will be performed
- *   asynchronously.  When the transfer completes, the USB host driver will
- *   call the complete() method of the struct usbhost_class_s interface.
- *   Only one transfer may be queued; Neither this method nor the transfer()
- *   method can be called again until the class complete() method has been called.
+ *   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
+ *   until the control transfer functions returns.
+ *
+ *   These are blocking methods; these functions will not return until the
+ *   control transfer has completed.
  *
  * Input Parameters:
  *   drvr - The USB host driver instance obtained as a parameter from the call to
@@ -279,19 +253,20 @@
  *
  ************************************************************************************/
 
-#define DRVR_CONTROL(drvr,req,buffer) ((drvr)->control(drvr,req,buffer))
+#define DRVR_CTRLIN(drvr,req,buffer)  ((drvr)->ctrlin(drvr,req,buffer))
+#define DRVR_CTRLOUT(drvr,req,buffer) ((drvr)->ctrlout(drvr,req,buffer))
 
 /************************************************************************************
  * Name: DRVR_TRANSFER
  *
  * Description:
- *   Enqueue a request to handle a transfer descriptor.  This method will
- *   enqueue the transfer request and return immediately.  The transfer will
- *   be performed asynchronously.  When the transfer completes, the USB host
- *   driver will call the complete() method of the struct usbhost_class_s
- *   interface.  Only one transfer may be queued; Neither this method nor the
- *   control method can be called again until the class complete() method has
- *   been called.
+ *   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
+ *   again until this function returns.
+ *
+ *   This is a blocking method; this functions will not return until the
+ *   transfer has completed.
  *
  * Input Parameters:
  *   drvr - The USB host driver instance obtained as a parameter from the call to
@@ -402,12 +377,6 @@ struct usbhost_class_s
 
   int (*configdesc)(FAR struct usbhost_class_s *class, FAR const uint8_t *configdesc, int desclen);
 
-  /* This method must be called by the USB host driver whenever a transfer
-   * completes.
-   */
-
-  int (*complete)(FAR struct usbhost_class_s *class, FAR const uint8_t *response, int resplen);
-
   /* This method informs the class that the USB device has been disconnected. */
 
   int (*disconnected)(FAR struct usbhost_class_s *class);
@@ -444,25 +413,29 @@ struct usbhost_driver_s
                FAR uint8_t **buffer, FAR size_t *maxlen);
   int (*free)(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
 
-  /* Enqueue a request on the control endpoint.  This method will enqueue
-   * the request and return immediately.  The transfer will be performed
-   * asynchronously.  When the transfer completes, the USB host driver will
-   * call the complete() method of the struct usbhost_class_s interface.
-   * Only one transfer may be queued; Neither this method nor the transfer()
-   * method can be called again until the class complete() method has been called.
+  /* 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
+   * until the control transfer functions returns.
+   *
+   * These are blocking methods; these functions will not return until the
+   * control transfer has completed.
    */
 
-  int (*control)(FAR struct usbhost_driver_s *drvr,
-                 const struct usb_ctrlreq_s *req,
-                 FAR uint8_t *buffer);
-
-  /* Enqueue a request to handle a transfer descriptor.  This method will
-   * enqueue the transfer request and return immediately.  The transfer will
-   * be performed asynchronously.  When the transfer completes, the USB host
-   * driver will call the complete() method of the struct usbhost_class_s
-   * interface.  Only one transfer may be queued; Neither this method nor the
-   * control method can be called again until the class complete() method has
-   * been called.
+  int (*ctrlin)(FAR struct usbhost_driver_s *drvr,
+                FAR const struct usb_ctrlreq_s *req,
+                FAR uint8_t *buffer);
+  int (*ctrlout)(FAR struct usbhost_driver_s *drvr,
+                 FAR const struct usb_ctrlreq_s *req,
+                 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
+   * again until this function returns.
+   *
+   * This is a blocking method; this functions will not return until the
+   * transfer has completed.
    */
 
   int (*transfer)(FAR struct usbhost_driver_s *drvr,
-- 
GitLab