nuttx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aguettou...@apache.org
Subject [incubator-nuttx] branch master updated: Check return from nxsem_wait_initialize()
Date Mon, 30 Mar 2020 20:53:19 GMT
This is an automated email from the ASF dual-hosted git repository.

aguettouche pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new d9b42ce  Check return from nxsem_wait_initialize()
d9b42ce is described below

commit d9b42cebe7034171844e7faf4e627a5bc9b5825f
Author: Gregory Nutt <gnutt@nuttx.org>
AuthorDate: Mon Mar 30 14:20:53 2020 -0600

    Check return from nxsem_wait_initialize()
    
    Resolution of Issue 619 will require multiple steps, this part of the first step in that resolution:  Every call to nxsem_wait_uninterruptible() must handle the return value from nxsem_wait_uninterruptible properly.  This commit is only for those files under drivers/usbhost.
---
 drivers/usbhost/usbhost_cdcacm.c         | 165 ++++--
 drivers/usbhost/usbhost_devaddr.c        |  74 +--
 drivers/usbhost/usbhost_hidkbd.c         | 493 ++++++++++------
 drivers/usbhost/usbhost_hidmouse.c       | 265 +++++----
 drivers/usbhost/usbhost_max3421e.c       | 942 ++++++++++++++++++-------------
 drivers/usbhost/usbhost_skeleton.c       | 169 +++---
 drivers/usbhost/usbhost_storage.c        | 105 +++-
 drivers/usbhost/usbhost_xboxcontroller.c | 371 +++++++-----
 8 files changed, 1601 insertions(+), 983 deletions(-)

diff --git a/drivers/usbhost/usbhost_cdcacm.c b/drivers/usbhost/usbhost_cdcacm.c
index e1ee508..d771050 100644
--- a/drivers/usbhost/usbhost_cdcacm.c
+++ b/drivers/usbhost/usbhost_cdcacm.c
@@ -1,36 +1,20 @@
 /****************************************************************************
  * drivers/usbhost/usbhost_cdcacm.c
  *
- *   Copyright (C) 2015-2017, 2019 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -303,7 +287,8 @@ struct usbhost_freestate_s
 
 /* Semaphores */
 
-static void usbhost_takesem(FAR sem_t *sem);
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Memory allocation services */
@@ -374,7 +359,8 @@ static int  usbhost_setup(FAR struct uart_dev_s *uartdev);
 static void usbhost_shutdown(FAR struct uart_dev_s *uartdev);
 static int  usbhost_attach(FAR struct uart_dev_s *uartdev);
 static void usbhost_detach(FAR struct uart_dev_s *uartdev);
-static int  usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static int  usbhost_ioctl(FAR struct file *filep, int cmd,
+              unsigned long arg);
 static void usbhost_rxint(FAR struct uart_dev_s *uartdev, bool enable);
 static bool usbhost_rxavailable(FAR struct uart_dev_s *uartdev);
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
@@ -486,9 +472,37 @@ static uint32_t g_devinuse;
  *
  ****************************************************************************/
 
-static void usbhost_takesem(FAR sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
+{
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -983,7 +997,8 @@ static void usbhost_txdata_work(FAR void *arg)
            * the device is disconnected).
            */
 
-          uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n", (int)nwritten);
+          uerr("ERROR: DRVR_TRANSFER for packet failed: %d\n",
+               (int)nwritten);
           break;
         }
     }
@@ -1315,8 +1330,8 @@ static void usbhost_destroy(FAR void *arg)
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -1386,7 +1401,8 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
 
         case USB_DESC_TYPE_INTERFACE:
           {
-            FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc;
+            FAR struct usb_ifdesc_s *ifdesc =
+              (FAR struct usb_ifdesc_s *)configdesc;
 
             uinfo("Interface descriptor: class: %d subclass: %d proto: %d\n",
                   ifdesc->classid, ifdesc->subclass, ifdesc->protocol);
@@ -1433,7 +1449,8 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
 
         case USB_DESC_TYPE_ENDPOINT:
           {
-            FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
 
             uinfo("Endpoint descriptor: currif: %02x attr: %02x\n",
                   currif, epdesc->attr);
@@ -1442,7 +1459,8 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
             /* Check for a bulk endpoint. */
 
             if (currif == USBHOST_DATAIF_FOUND &&
-                (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK)
+                (epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_BULK)
               {
                 /* Yes.. it is a bulk endpoint.  IN or OUT? */
 
@@ -1466,11 +1484,13 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
                     /* Save the bulk OUT endpoint information */
 
                     boutdesc.hport        = hport;
-                    boutdesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    boutdesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
                     boutdesc.in           = false;
                     boutdesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
                     boutdesc.interval     = epdesc->interval;
-                    boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    boutdesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
 
                     uinfo("Bulk OUT EP addr:%d mxpacketsize:%d\n",
                           boutdesc.addr, boutdesc.mxpacketsize);
@@ -1495,11 +1515,14 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
                     /* Save the bulk IN endpoint information */
 
                     bindesc.hport        = hport;
-                    bindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    bindesc.addr         = epdesc->addr &
+                                           USB_EP_ADDR_NUMBER_MASK;
                     bindesc.in           = 1;
                     bindesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
                     bindesc.interval     = epdesc->interval;
-                    bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    bindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uinfo("Bulk IN EP addr:%d mxpacketsize:%d\n",
                           bindesc.addr, bindesc.mxpacketsize);
                   }
@@ -1539,11 +1562,13 @@ static int usbhost_cfgdesc(FAR struct usbhost_cdcacm_s *priv,
                     /* Save the bulk OUT endpoint information */
 
                     iindesc.hport        = hport;
-                    iindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    iindesc.addr         = epdesc->addr &
+                                           USB_EP_ADDR_NUMBER_MASK;
                     iindesc.in           = false;
                     iindesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     iindesc.interval     = epdesc->interval;
-                    iindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    iindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
 
                     uinfo("Interrupt IN EP addr:%d mxpacketsize:%d\n",
                           boutdesc.addr, boutdesc.mxpacketsize);
@@ -1865,12 +1890,13 @@ static void usbhost_free_buffers(FAR struct usbhost_cdcacm_s *priv)
  * Name: usbhost_create
  *
  * Description:
- *   This function implements the create() method of struct usbhost_registry_s.
- *   The create() method is a callback into the class implementation.  It is
- *   used to (1) create a new instance of the USB host class state and to (2)
- *   bind a USB host driver "session" to the class instance.  Use of this
- *   create() method will support environments where there may be multiple
- *   USB ports and multiple USB devices simultaneously connected.
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
  *
  * Input Parameters:
  *   hport - The hub port that manages the new class instance.
@@ -1978,8 +2004,8 @@ usbhost_create(FAR struct usbhost_hubport_s *hport,
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  *   NOTE that the class instance remains valid upon return with a failure.
  *   It is the responsibility of the higher level enumeration logic to call
@@ -1995,7 +2021,8 @@ usbhost_create(FAR struct usbhost_hubport_s *hport,
 static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
                            FAR const uint8_t *configdesc, int desclen)
 {
-  FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)usbclass;
+  FAR struct usbhost_cdcacm_s *priv =
+    (FAR struct usbhost_cdcacm_s *)usbclass;
 #ifdef HAVE_INTIN_ENDPOINT
   FAR struct usbhost_hubport_s *hport;
 #endif
@@ -2013,7 +2040,11 @@ static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
 
   /* Get exclusive access to the device structure */
 
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Increment the reference count.  This will prevent usbhost_destroy() from
    * being called asynchronously if the device is removed.
@@ -2128,7 +2159,8 @@ errout:
 
 static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass)
 {
-  FAR struct usbhost_cdcacm_s *priv = (FAR struct usbhost_cdcacm_s *)usbclass;
+  FAR struct usbhost_cdcacm_s *priv =
+    (FAR struct usbhost_cdcacm_s *)usbclass;
   FAR struct usbhost_hubport_s *hport;
   irqstate_t flags;
   int ret;
@@ -2238,7 +2270,11 @@ static int usbhost_setup(FAR struct uart_dev_s *uartdev)
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the CDC/ACM device is still connected.  We need to disable
    * interrupts momentarily to assure that there are no asynchronous
@@ -2289,7 +2325,7 @@ static void usbhost_shutdown(FAR struct uart_dev_s *uartdev)
   /* Decrement the reference count on the block driver */
 
   DEBUGASSERT(priv->crefs > 1);
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
   priv->crefs--;
 
   /* Release the semaphore.  The following operations when crefs == 1 are
@@ -2348,8 +2384,8 @@ static int usbhost_attach(FAR struct uart_dev_s *uartdev)
  *
  * Description:
  *   Detach USART interrupts.  This method is called when the serial port is
- *   closed normally just before the shutdown method is called.  The exception
- *   is the serial console which is never shutdown.
+ *   closed normally just before the shutdown method is called.  The
+ *   exception is the serial console which is never shutdown.
  *
  ****************************************************************************/
 
@@ -2396,7 +2432,12 @@ static int usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
     {
       /* Process the IOCTL by command */
 
-      usbhost_takesem(&priv->exclsem);
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
+
       switch (cmd)
         {
 #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
diff --git a/drivers/usbhost/usbhost_devaddr.c b/drivers/usbhost/usbhost_devaddr.c
index 8aa68bf..467174b 100644
--- a/drivers/usbhost/usbhost_devaddr.c
+++ b/drivers/usbhost/usbhost_devaddr.c
@@ -2,35 +2,20 @@
  * drivers/usbhost/usbhost_devaddr.c
  * Manage USB device addresses
  *
- *   Copyright (C) 2013, 2015, 2017 Gregory Nutt. All rights reserved.
- *   Authors: Gregory Nutt <gnutt@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ *   http://www.apache.org/licenses/LICENSE-2.0
  *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -65,9 +50,9 @@
  *
  ****************************************************************************/
 
-static void usbhost_takesem(FAR struct usbhost_devaddr_s *devgen)
+static int usbhost_takesem(FAR struct usbhost_devaddr_s *devgen)
 {
-  nxsem_wait_uninterruptible(&devgen->exclsem);
+  return nxsem_wait_uninterruptible(&devgen->exclsem);
 }
 
 #define usbhost_givesem(devgen) nxsem_post(&devgen->exclsem)
@@ -183,8 +168,8 @@ usbhost_roothubport(FAR struct usbhost_hubport_s *hport)
 
   while (hport->parent != NULL)
     {
-      /* This is not a root hub port.  It is a port on a hub.  Try the port of
-       * the parent hub that supports this port.
+      /* This is not a root hub port.  It is a port on a hub.  Try the port
+       * of the parent hub that supports this port.
        */
 
       hport = hport->parent;
@@ -269,6 +254,7 @@ int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport)
 {
   FAR struct usbhost_devaddr_s *devgen;
   int devaddr;
+  int ret;
 
   /* Get the address generation data from the root hub port */
 
@@ -278,7 +264,11 @@ int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport)
 
   /* Get exclusive access to the root hub port device address data */
 
-  usbhost_takesem(devgen);
+  ret = usbhost_takesem(devgen);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Allocate a device address */
 
@@ -297,7 +287,8 @@ int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport)
  * Name: usbhost_devaddr_destroy
  *
  * Description:
- *   Release a device address previously assigned by usbhost_devaddr_create().
+ *   Release a device address previously assigned by
+ *   usbhost_devaddr_create().
  *
  * Input Parameters:
  *   hport - A reference to a hub port structure from which a device has been
@@ -309,9 +300,11 @@ int usbhost_devaddr_create(FAR struct usbhost_hubport_s *hport)
  *
  ****************************************************************************/
 
-void usbhost_devaddr_destroy(FAR struct usbhost_hubport_s *hport, uint8_t devaddr)
+void usbhost_devaddr_destroy(FAR struct usbhost_hubport_s *hport,
+                             uint8_t devaddr)
 {
   FAR struct usbhost_devaddr_s *devgen;
+  int ret;
 
   /* Ignore bad device address */
 
@@ -325,7 +318,18 @@ void usbhost_devaddr_destroy(FAR struct usbhost_hubport_s *hport, uint8_t devadd
 
       /* Get exclusive access to the root hub port device address data */
 
-      usbhost_takesem(devgen);
+      do
+        {
+          ret = usbhost_takesem(devgen);
+
+          /* The only expected error would -ECANCELED meaning that the parent
+           * thread has been canceled.  We have to continue and free the
+           * device address in this case.
+           */
+
+          DEBUGASSERT(ret == OK || ret == -ECANCELED);
+        }
+      while (ret < 0);
 
       /* Free the device address */
 
diff --git a/drivers/usbhost/usbhost_hidkbd.c b/drivers/usbhost/usbhost_hidkbd.c
index 879572c..073f225 100644
--- a/drivers/usbhost/usbhost_hidkbd.c
+++ b/drivers/usbhost/usbhost_hidkbd.c
@@ -1,35 +1,20 @@
 /****************************************************************************
  * drivers/usbhost/usbhost_hidkbd.c
  *
- *   Copyright (C) 2011-2013, 2015-2017 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -254,7 +239,8 @@ struct usbhost_outstream_s
 
 /* Semaphores */
 
-static void usbhost_takesem(sem_t *sem);
+static int  usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Polling support */
@@ -268,28 +254,31 @@ static inline void usbhost_freeclass(FAR struct usbhost_state_s *usbclass);
 
 /* Device name management */
 
-static int usbhost_allocdevno(FAR struct usbhost_state_s *priv);
+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);
+static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
+              FAR char *devname);
 
 /* Keyboard polling thread */
 
 static void usbhost_destroy(FAR void *arg);
-static void usbhost_putbuffer(FAR struct usbhost_state_s *priv, uint8_t keycode);
+static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
+              uint8_t keycode);
 #ifdef CONFIG_HIDKBD_ENCODED
 static void usbhost_putstream(FAR struct lib_outstream_s *this, int ch);
 #endif
-static inline uint8_t usbhost_mapscancode(uint8_t scancode, uint8_t modifier);
+static inline uint8_t usbhost_mapscancode(uint8_t scancode,
+              uint8_t modifier);
 #ifdef CONFIG_HIDKBD_ENCODED
 static inline void usbhost_encodescancode(FAR struct usbhost_state_s *priv,
-                                          uint8_t scancode, uint8_t modifier);
+              uint8_t scancode, uint8_t modifier);
 #endif
-static int usbhost_kbdpoll(int argc, char *argv[]);
+static int  usbhost_kbdpoll(int argc, char *argv[]);
 
 /* Helpers for usbhost_connect() */
 
 static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
-                                  FAR const uint8_t *configdesc, int desclen);
+              FAR const uint8_t *configdesc, int desclen);
 static inline int usbhost_devinit(FAR struct usbhost_state_s *priv);
 
 /* (Little Endian) Data helpers */
@@ -308,26 +297,26 @@ static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv);
 
 /* struct usbhost_registry_s methods */
 
-static struct usbhost_class_s *
-  usbhost_create(FAR struct usbhost_hubport_s *hport,
-                 FAR const struct usbhost_id_s *id);
+static struct usbhost_class_s *usbhost_create(
+              FAR struct usbhost_hubport_s *hport,
+              FAR const struct usbhost_id_s *id);
 
 /* struct usbhost_class_s methods */
 
-static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
-                           FAR const uint8_t *configdesc, int desclen);
-static int usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
+static int  usbhost_connect(FAR struct usbhost_class_s *usbclass,
+                            FAR const uint8_t *configdesc, int desclen);
+static int  usbhost_disconnected(FAR struct usbhost_class_s *usbclass);
 
 /* Driver methods.  We export the keyboard as a standard character driver */
 
-static int usbhost_open(FAR struct file *filep);
-static int usbhost_close(FAR struct file *filep);
+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);
+              FAR char *buffer, size_t len);
 static ssize_t usbhost_write(FAR struct file *filep,
-                             FAR const char *buffer, size_t len);
-static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
-                        bool setup);
+              FAR const char *buffer, size_t len);
+static int  usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
+              bool setup);
 
 /****************************************************************************
  * Private Data
@@ -401,35 +390,59 @@ static const uint8_t encoding[USBHID_NUMENCODINGS] =
 {
   /* 0x28-0x2f: Enter,escape,del,back-tab,space,_,+,{ */
 
-  KEYCODE_ENTER,   0,                   KEYCODE_FWDDEL,     KEYCODE_BACKDEL,  0,                   0,             0,                0,
+  KEYCODE_ENTER,        0,
+  KEYCODE_FWDDEL,       KEYCODE_BACKDEL,
+  0,                    0,
+  0,                    0,
 
   /* 0x30-0x37: },|,Non-US tilde,:,",grave tilde,<,> */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0x38-0x3f: /,CapsLock,F1,F2,F3,F4,F5,F6 */
 
-  0,               KEYCODE_CAPSLOCK,    KEYCODE_F1,        KEYCODE_F2,       KEYCODE_F3,          KEYCODE_F4,    KEYCODE_F5,       KEYCODE_F6,
+  0,                    KEYCODE_CAPSLOCK,
+  KEYCODE_F1,           KEYCODE_F2,
+  KEYCODE_F3,           KEYCODE_F4,
+  KEYCODE_F5,           KEYCODE_F6,
 
   /* 0x40-0x47: F7,F8,F9,F10,F11,F12,PrtScn,ScrollLock */
 
-  KEYCODE_F7,      KEYCODE_F8,          KEYCODE_F9,        KEYCODE_F10,      KEYCODE_F11,         KEYCODE_F12,   KEYCODE_PRTSCRN,  KEYCODE_SCROLLLOCK,
+  KEYCODE_F7,           KEYCODE_F8,
+  KEYCODE_F9,           KEYCODE_F10,
+  KEYCODE_F11,          KEYCODE_F12,
+  KEYCODE_PRTSCRN,      KEYCODE_SCROLLLOCK,
 
   /* 0x48-0x4f: Pause,Insert,Home,PageUp,DeleteForward,End,PageDown,RightArrow */
 
-  KEYCODE_PAUSE,   KEYCODE_INSERT,      KEYCODE_HOME,      KEYCODE_PAGEUP,   KEYCODE_FWDDEL,      KEYCODE_END,   KEYCODE_PAGEDOWN, KEYCODE_RIGHT,
+  KEYCODE_PAUSE,        KEYCODE_INSERT,
+  KEYCODE_HOME,         KEYCODE_PAGEUP,
+  KEYCODE_FWDDEL,       KEYCODE_END,
+  KEYCODE_PAGEDOWN,     KEYCODE_RIGHT,
 
   /* 0x50-0x57: LeftArrow,DownArrow,UpArrow,Num Lock,/,*,-,+ */
 
-  KEYCODE_LEFT,    KEYCODE_DOWN,        KEYCODE_UP,        KEYCODE_NUMLOCK,  0,                   0,             0,                0,
+  KEYCODE_LEFT,         KEYCODE_DOWN,
+  KEYCODE_UP,           KEYCODE_NUMLOCK,
+  0,                    0,
+  0,                    0,
 
   /* 0x58-0x5f: Enter,1-7 */
 
-  KEYCODE_ENTER,   0,                   0,                 0,                0,                   0,             0,                0,
+  KEYCODE_ENTER,        0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0x60-0x66: 8-9,0,.,Non-US \,Application,Power */
 
-  0,               0,                   0,                 0,                0,                   0,             KEYCODE_POWER,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  KEYCODE_POWER,
 
 #ifdef CONFIG_HIDKBD_ALLSCANCODES
 
@@ -437,63 +450,107 @@ static const uint8_t encoding[USBHID_NUMENCODINGS] =
 
   /* 0x68-0x6f: F13,F14,F15,F16,F17,F18,F19,F20 */
 
-  KEYCODE_F13,     KEYCODE_F14,         KEYCODE_F15,       KEYCODE_F16,      KEYCODE_F17,         KEYCODE_F18,   KEYCODE_F19,      KEYCODE_F20,
+  KEYCODE_F13,          KEYCODE_F14,
+  KEYCODE_F15,          KEYCODE_F16,
+  KEYCODE_F17,          KEYCODE_F18,
+  KEYCODE_F19,          KEYCODE_F20,
 
   /* 0x70-0x77: F21,F22,F23,F24,Execute,Help,Menu,Select */
 
-  KEYCODE_F21,     KEYCODE_F22,         KEYCODE_F23,       KEYCODE_F24,      KEYCODE_EXECUTE,     KEYCODE_HELP,  KEYCODE_MENU,     KEYCODE_SELECT,
+  KEYCODE_F21,          KEYCODE_F22,
+  KEYCODE_F23,          KEYCODE_F24,
+  KEYCODE_EXECUTE,      KEYCODE_HELP,
+  KEYCODE_MENU,         KEYCODE_SELECT,
 
   /* 0x78-0x7f: Stop,Again,Undo,Cut,Copy,Paste,Find,Mute */
 
-  KEYCODE_STOP,    KEYCODE_AGAIN,       KEYCODE_UNDO,      KEYCODE_CUT,      KEYCODE_COPY,        KEYCODE_PASTE, KEYCODE_FIND,     KEYCODE_MUTE,
+  KEYCODE_STOP,         KEYCODE_AGAIN,
+  KEYCODE_UNDO,         KEYCODE_CUT,
+  KEYCODE_COPY,         KEYCODE_PASTE,
+  KEYCODE_FIND,         KEYCODE_MUTE,
 
   /* 0x80-0x87: VolUp,VolDown,LCapsLock,lNumLock,LScrollLock,,,=,International1 */
 
-  KEYCODE_VOLUP,   KEYCODE_VOLDOWN,     KEYCODE_LCAPSLOCK, KEYCODE_LNUMLOCK, KEYCODE_LSCROLLLOCK, 0,             0,                0,
+  KEYCODE_VOLUP,        KEYCODE_VOLDOWN,
+  KEYCODE_LCAPSLOCK,    KEYCODE_LNUMLOCK,
+  KEYCODE_LSCROLLLOCK,  0,
+  0,                    0,
 
   /* 0x88-0x8f: International 2-9 */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0x90-0x97: LAN 1-8 */
 
-  KEYCODE_LANG1,   KEYCODE_LANG2,       KEYCODE_LANG3,     KEYCODE_LANG4,    KEYCODE_LANG5,       KEYCODE_LANG6, KEYCODE_LANG7,    KEYCODE_LANG8,
+  KEYCODE_LANG1,        KEYCODE_LANG2,
+  KEYCODE_LANG3,        KEYCODE_LANG4,
+  KEYCODE_LANG5,        KEYCODE_LANG6,
+  KEYCODE_LANG7,        KEYCODE_LANG8,
 
   /* 0x98-0x9f: LAN 9,Erase,SysReq,Cancel,Clear,Prior,Return,Separator */
 
-  0,               0,                   KEYCODE_SYSREQ,    KEYCODE_CANCEL,   KEYCODE_CLEAR,       0,             KEYCODE_ENTER,    0,
+  0,                    0,
+  KEYCODE_SYSREQ,       KEYCODE_CANCEL,
+  KEYCODE_CLEAR,        0,
+  KEYCODE_ENTER,        0,
 
   /* 0xa0-0xa7: Out,Oper,Clear,CrSel,Excel,(reserved) */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                 0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0xa8-0xaf: (reserved) */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                 0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0xb0-0xb7: 00,000,ThouSeparator,DecSeparator,CurrencyUnit,SubUnit,(,) */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                 0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0xb8-0xbf: {,},tab,backspace,A-D */
 
-  0,               0,                   0,                 KEYCODE_BACKDEL,  0,                   0,             0,                 0,
+  0,                    0,
+  0,                    KEYCODE_BACKDEL,
+  0,                    0,
+  0,                    0,
 
   /* 0xc0-0xc7: E-F,XOR,^,%,<,>,& */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                 0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0xc8-0xcf: &&,|,||,:,#, ,@,! */
 
-  0,               0,                   0,                 0,                0,                   0,             0,                 0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
+  0,                    0,
 
   /* 0xd0-0xd7: Memory Store,Recall,Clear,Add,Subtract,Muliply,Divide,+/- */
 
-  KEYCODE_MEMSTORE, KEYCODE_MEMRECALL,  KEYCODE_MEMCLEAR,  KEYCODE_MEMADD,   KEYCODE_MEMSUB,     KEYCODE_MEMMUL, KEYCODE_MEMDIV,    KEYCODE_NEGATE,
+  KEYCODE_MEMSTORE,     KEYCODE_MEMRECALL,
+  KEYCODE_MEMCLEAR,     KEYCODE_MEMADD,
+  KEYCODE_MEMSUB,       KEYCODE_MEMMUL,
+  KEYCODE_MEMDIV,       KEYCODE_NEGATE,
 
   /* 0xd8-0xdd: Clear,ClearEntry,Binary,Octal,Decimal,Hexadecimal */
 
-  KEYCODE_CLEAR,    KEYCODE_CLEARENTRY, KEYCODE_BINARY,    KEYCODE_OCTAL,    KEYCODE_DECIMAL,    KEYCODE_HEXADECIMAL
+  KEYCODE_CLEAR,        KEYCODE_CLEARENTRY,
+  KEYCODE_BINARY,       KEYCODE_OCTAL,
+  KEYCODE_DECIMAL,      KEYCODE_HEXADECIMAL
 #endif
 };
 
@@ -583,9 +640,37 @@ static const uint8_t lcmap[USBHID_NUMSCANCODES] =
  *
  ****************************************************************************/
 
-static void usbhost_takesem(sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -635,7 +720,10 @@ static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
   FAR struct usbhost_state_s *priv;
 
   DEBUGASSERT(!up_interrupt_context());
-  priv = (FAR struct usbhost_state_s *)kmm_malloc(sizeof(struct usbhost_state_s));
+
+  priv = (FAR struct usbhost_state_s *)
+    kmm_malloc(sizeof(struct usbhost_state_s));
+
   uinfo("Allocated: %p\n", priv);
   return priv;
 }
@@ -706,7 +794,8 @@ static void usbhost_freedevno(FAR struct usbhost_state_s *priv)
     }
 }
 
-static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv, char *devname)
+static inline void usbhost_mkdevname(FAR struct usbhost_state_s *priv,
+                                     FAR char *devname)
 {
   snprintf(devname, DEV_NAMELEN, DEV_FORMAT, priv->devchar);
 }
@@ -857,7 +946,8 @@ static void usbhost_putbuffer(FAR struct usbhost_state_s *priv,
 #ifdef CONFIG_HIDKBD_ENCODED
 static void usbhost_putstream(FAR struct lib_outstream_s *stream, int ch)
 {
-  FAR struct usbhost_outstream_s *privstream = (FAR struct usbhost_outstream_s *)stream;
+  FAR struct usbhost_outstream_s *privstream =
+    (FAR struct usbhost_outstream_s *)stream;
 
   DEBUGASSERT(privstream && privstream->priv);
   usbhost_putbuffer(privstream->priv, (uint8_t)ch);
@@ -980,8 +1070,12 @@ static int usbhost_kbdpoll(int argc, char *argv[])
   FAR struct usb_ctrlreq_s *ctrlreq;
   irqstate_t flags;
 #ifndef CONFIG_HIDKBD_NODEBOUNCE
-  uint8_t lastkey[6] = {0, 0, 0, 0, 0, 0};
+  uint8_t lastkey[6] =
+  {
+    0, 0, 0, 0, 0, 0
+  };
 #endif
+
 #if defined(CONFIG_DEBUG_USB) && defined(CONFIG_DEBUG_INFO)
   unsigned int npolls = 0;
 #endif
@@ -997,10 +1091,10 @@ static int usbhost_kbdpoll(int argc, char *argv[])
    * 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 *not* incremented here.  When the driver
-   * structure was created, it was created with a reference count of one.  This
-   * thread is responsible for that count.  The count will be decrement when
-   * this thread exits.
+   * NOTE: that the reference count is *not* incremented here.  When the
+   * driver structure was created, it was created with a reference count of
+   * one.  This thread is responsible for that count.  The count will be
+   * decrement when this thread exits.
    */
 
   priv = g_priv;
@@ -1022,7 +1116,11 @@ static int usbhost_kbdpoll(int argc, char *argv[])
        * open and actively trying to interact with the class driver.
        */
 
-      usbhost_takesem(&priv->exclsem);
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
 
       /* Format the HID report request:
        *
@@ -1035,7 +1133,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
        */
 
       ctrlreq       = (struct usb_ctrlreq_s *)priv->tbuffer;
-      ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE;
+      ctrlreq->type = USB_REQ_DIR_IN | USB_REQ_TYPE_CLASS |
+                      USB_REQ_RECIPIENT_INTERFACE;
       ctrlreq->req  = USBHID_REQUEST_GETREPORT;
 
       usbhost_putle16(ctrlreq->value, (USBHID_REPORTTYPE_INPUT << 8));
@@ -1070,9 +1169,10 @@ static int usbhost_kbdpoll(int argc, char *argv[])
 
       else if (priv->open)
         {
-          struct usbhid_kbdreport_s *rpt = (struct usbhid_kbdreport_s *)priv->tbuffer;
-          uint8_t                    keycode;
-          int                        i;
+          struct usbhid_kbdreport_s *rpt =
+            (struct usbhid_kbdreport_s *)priv->tbuffer;
+          uint8_t keycode;
+          int i;
 
           /* Success, reset the error counter */
 
@@ -1080,7 +1180,12 @@ static int usbhost_kbdpoll(int argc, char *argv[])
 
           /* Add the newly received keystrokes to our internal buffer */
 
-          usbhost_takesem(&priv->exclsem);
+          ret = usbhost_takesem(&priv->exclsem);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
           for (i = 0; i < 6; i++)
             {
               /* Is this key pressed?  But not pressed last time?
@@ -1121,7 +1226,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
 
                   keycode = usbhost_mapscancode(rpt->key[i], rpt->modifier);
                   iinfo("Key %d: %02x keycode:%c modifier: %02x\n",
-                         i, rpt->key[i], keycode ? keycode : ' ', rpt->modifier);
+                         i, rpt->key[i], keycode ? keycode : ' ',
+                         rpt->modifier);
 
                   /* Zero at this point means that the key does not map to a
                    * printable character.
@@ -1133,7 +1239,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
                        * a valid, NUL character.
                        */
 
-                      if ((rpt->modifier & (USBHID_MODIFER_LCTRL | USBHID_MODIFER_RCTRL)) != 0)
+                      if ((rpt->modifier & (USBHID_MODIFER_LCTRL |
+                                            USBHID_MODIFER_RCTRL)) != 0)
                         {
                           keycode &= 0x1f;
                         }
@@ -1145,14 +1252,16 @@ static int usbhost_kbdpoll(int argc, char *argv[])
                       usbhost_putbuffer(priv, keycode);
                     }
 
-                  /* The zero might, however, map to a special keyboard action (such as a
-                   * cursor movement or function key).  Attempt to encode the special key.
+                  /* The zero might, however, map to a special keyboard
+                   * action (such as a cursor movement or function key).
+                   * Attempt to encode the special key.
                    */
 
 #ifdef CONFIG_HIDKBD_ENCODED
                   else
                     {
-                      usbhost_encodescancode(priv, rpt->key[i], rpt->modifier);
+                      usbhost_encodescancode(priv, rpt->key[i],
+                                             rpt->modifier);
                     }
 #endif
                 }
@@ -1207,6 +1316,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
           uinfo("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.
@@ -1236,7 +1346,7 @@ static int usbhost_kbdpoll(int argc, char *argv[])
    * trying to interact with the class driver.
    */
 
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
 
   /* Indicate that we are no longer running and decrement the reference
    * count held by this thread.  If there are no other users of the class,
@@ -1301,8 +1411,8 @@ static int usbhost_kbdpoll(int argc, char *argv[])
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -1365,7 +1475,8 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_INTERFACE:
           {
-            FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc;
+            FAR struct usb_ifdesc_s *ifdesc =
+              (FAR struct usb_ifdesc_s *)configdesc;
 
             uinfo("Interface descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
@@ -1404,21 +1515,23 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_ENDPOINT:
           {
-            FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
 
             uinfo("Endpoint descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
 
             /* Check for an interrupt endpoint. */
 
-            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
+            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_INT)
               {
                 /* Yes.. it is a interrupt endpoint.  IN or OUT? */
 
                 if (USB_ISEPOUT(epdesc->addr))
                   {
-                    /* It is an interrupt OUT endpoint.  There not be more than one
-                     * interrupt OUT endpoint.
+                    /* It is an interrupt OUT endpoint.  There not be more
+                     * than one interrupt OUT endpoint.
                      */
 
                     if ((found & USBHOST_EPOUTFOUND) != 0)
@@ -1435,11 +1548,14 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the interrupt OUT endpoint information */
 
                     epoutdesc.hport        = hport;
-                    epoutdesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    epoutdesc.addr         = epdesc->addr &
+                                             USB_EP_ADDR_NUMBER_MASK;
                     epoutdesc.in           = false;
                     epoutdesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     epoutdesc.interval     = epdesc->interval;
-                    epoutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    epoutdesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uinfo("Interrupt OUT EP addr:%d mxpacketsize:%d\n",
                           epoutdesc.addr, epoutdesc.mxpacketsize);
                   }
@@ -1463,11 +1579,14 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the interrupt IN endpoint information */
 
                     epindesc.hport        = hport;
-                    epindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    epindesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
                     epindesc.in           = 1;
                     epindesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     epindesc.interval     = epdesc->interval;
-                    epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    epindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uinfo("Interrupt IN EP addr:%d mxpacketsize:%d\n",
                           epindesc.addr, epindesc.mxpacketsize);
                   }
@@ -1578,25 +1697,32 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
   priv->crefs++;
   DEBUGASSERT(priv->crefs == 2);
 
-  /* 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).
+  /* Start a worker task to poll the USB device.  It would be nice to use
+   * 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).
    */
 
   uinfo("Start poll task\n");
 
-  /* The inputs to a task started by kthread_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.
+  /* The inputs to a task started by kthread_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).
+   * 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);
+  ret = usbhost_takesem(&g_exclsem);
+  if (ret < 0)
+    {
+      usbhost_tdfree(priv);
+      goto errout;
+    }
+
   g_priv = priv;
 
   priv->pollpid = kthread_create("kbdpoll", CONFIG_HIDKBD_DEFPRIO,
@@ -1614,9 +1740,14 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 
   /* Now wait for the poll task to get properly initialized */
 
-  usbhost_takesem(&g_syncsem);
+  ret = usbhost_takesem(&g_syncsem);
   usbhost_givesem(&g_exclsem);
 
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
   /* Register the driver */
 
   uinfo("Register driver\n");
@@ -1628,9 +1759,10 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
    */
 
 errout:
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
   priv->crefs--;
   usbhost_givesem(&priv->exclsem);
+
   return ret;
 }
 
@@ -1693,7 +1825,8 @@ static inline uint32_t usbhost_getle32(const uint8_t *val)
 {
   /* Little endian means LS halfword first in byte stream */
 
-  return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
+  return (uint32_t)usbhost_getle16(&val[2]) << 16 |
+         (uint32_t)usbhost_getle16(val);
 }
 
 /****************************************************************************
@@ -1717,7 +1850,7 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
   /* Little endian means LS halfword first in byte stream */
 
   usbhost_putle16(dest, (uint16_t)(val & 0xffff));
-  usbhost_putle16(dest+2, (uint16_t)(val >> 16));
+  usbhost_putle16(dest + 2, (uint16_t)(val >> 16));
 }
 #endif
 
@@ -1736,7 +1869,7 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
+static int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
 {
   FAR struct usbhost_hubport_s *hport;
 
@@ -1762,7 +1895,7 @@ static inline int usbhost_tdalloc(FAR struct usbhost_state_s *priv)
  *
  ****************************************************************************/
 
-static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
+static int usbhost_tdfree(FAR struct usbhost_state_s *priv)
 {
   FAR struct usbhost_hubport_s *hport;
   int result = OK;
@@ -1789,12 +1922,13 @@ static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
  * Name: usbhost_create
  *
  * Description:
- *   This function implements the create() method of struct usbhost_registry_s.
- *   The create() method is a callback into the class implementation.  It is
- *   used to (1) create a new instance of the USB host class state and to (2)
- *   bind a USB host driver "session" to the class instance.  Use of this
- *   create() method will support environments where there may be multiple
- *   USB ports and multiple USB devices simultaneously connected.
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
  *
  * Input Parameters:
  *   hport - The hub port that manages the new class instance.
@@ -1829,7 +1963,7 @@ static FAR struct usbhost_class_s *
 
       if (usbhost_allocdevno(priv) == OK)
         {
-         /* Initialize class method function pointers */
+          /* Initialize class method function pointers */
 
           priv->usbclass.hport        = hport;
           priv->usbclass.connect      = usbhost_connect;
@@ -1869,9 +2003,6 @@ static FAR struct usbhost_class_s *
 }
 
 /****************************************************************************
- * struct usbhost_class_s methods
- ****************************************************************************/
-/****************************************************************************
  * Name: usbhost_connect
  *
  * Description:
@@ -1881,17 +2012,18 @@ static FAR struct usbhost_class_s *
  *   descriptor to the class so that the class may initialize properly
  *
  * Input Parameters:
- *   usbclass - The USB host class entry previously obtained from a call to create().
+ *   usbclass   - The USB host class entry previously obtained from a call
+ *                to create().
  *   configdesc - A pointer to a uint8_t buffer container the configuration
- *     descriptor.
- *   desclen - The length in bytes of the configuration descriptor.
+ *                descriptor.
+ *   desclen    - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
- *   NOTE that the class instance remains valid upon return with a failure.  It is
- *   the responsibility of the higher level enumeration logic to call
+ *   NOTE that the class instance remains valid upon return with a failure.
+ *   It is the responsibility of the higher level enumeration logic to call
  *   CLASS_DISCONNECTED to free up the class driver resources.
  *
  * Assumptions:
@@ -2021,9 +2153,6 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
 }
 
 /****************************************************************************
- * Character driver methods
- ****************************************************************************/
-/****************************************************************************
  * Name: usbhost_open
  *
  * Description:
@@ -2046,11 +2175,15 @@ static int usbhost_open(FAR struct file *filep)
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the keyboard device is still connected.  We need to disable
-   * interrupts momentarily to assure that there are no asynchronous disconnect
-   * events.
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   flags = enter_critical_section();
@@ -2071,6 +2204,7 @@ static int usbhost_open(FAR struct file *filep)
       priv->open = true;
       ret        = OK;
     }
+
   leave_critical_section(flags);
 
   usbhost_givesem(&priv->exclsem);
@@ -2090,6 +2224,7 @@ static int usbhost_close(FAR struct file *filep)
   FAR struct inode *inode;
   FAR struct usbhost_state_s *priv;
   irqstate_t flags;
+  int ret;
 
   uinfo("Entry\n");
   DEBUGASSERT(filep && filep->f_inode);
@@ -2099,7 +2234,11 @@ static int usbhost_close(FAR struct file *filep)
   /* Decrement the reference count on the driver */
 
   DEBUGASSERT(priv->crefs >= 1);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* We need to disable interrupts momentarily to assure that there are no
    * asynchronous poll or disconnect events.
@@ -2120,12 +2259,12 @@ static int usbhost_close(FAR struct file *filep)
        *
        * 1) It might be zero meaning that the polling thread has already
        *    exited and decremented its count.
-       * 2) If might be one meaning either that (a) the polling thread is still
-       *    running and still holds a count, or (b) the polling thread has exited,
-       *    but there is still an outstanding open reference.
+       * 2) If might be one meaning either that (a) the polling thread is
+       *    still running and still holds a count, or (b) the polling thread
+       *    has exited, but there is still an outstanding open reference.
        */
 
-     if (priv->crefs == 0 || (priv->crefs == 1 && priv->polling))
+      if (priv->crefs == 0 || (priv->crefs == 1 && priv->polling))
         {
           /* Yes.. In either case, then the driver is no longer open */
 
@@ -2177,7 +2316,8 @@ 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_read(FAR struct file *filep, FAR char *buffer,
+                            size_t len)
 {
   FAR struct inode           *inode;
   FAR struct usbhost_state_s *priv;
@@ -2193,7 +2333,11 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the keyboard is still connected.  We need to disable interrupts
    * momentarily to assure that there are no asynchronous disconnect events.
@@ -2202,8 +2346,8 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
   if (priv->disconnected)
     {
       /* No... the driver is no longer bound to the class.  That means that
-       * the USB keyboard is no longer connected.  Refuse any further attempts
-       * to access the driver.
+       * the USB keyboard is no longer connected.  Refuse any further
+       * attempts to access the driver.
        */
 
       ret = -ENODEV;
@@ -2230,8 +2374,17 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
 
           priv->waiting = true;
           usbhost_givesem(&priv->exclsem);
-          usbhost_takesem(&priv->waitsem);
-          usbhost_takesem(&priv->exclsem);
+          ret = usbhost_takesem(&priv->waitsem);
+          if (ret < 0)
+            {
+              return ret;
+            }
+
+          ret = usbhost_takesem(&priv->exclsem);
+          if (ret < 0)
+            {
+              return ret;
+            }
 
           /* Did the keyboard become disconnected while we were waiting */
 
@@ -2248,16 +2401,16 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
            tail != priv->headndx && nbytes < len;
            nbytes++)
         {
-           /* Copy the next keyboard character into the user buffer */
+          /* Copy the next keyboard character into the user buffer */
 
-           *buffer++ = priv->kbdbuffer[tail];
+          *buffer++ = priv->kbdbuffer[tail];
 
-           /* Handle wrap-around of the tail index */
+          /* Handle wrap-around of the tail index */
 
-           if (++tail >= CONFIG_HIDKBD_BUFSIZE)
-             {
-               tail = 0;
-             }
+          if (++tail >= CONFIG_HIDKBD_BUFSIZE)
+            {
+              tail = 0;
+            }
         }
 
       ret = nbytes;
@@ -2301,7 +2454,7 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
 {
   FAR struct inode           *inode;
   FAR struct usbhost_state_s *priv;
-  int                         ret = OK;
+  int                         ret;
   int                         i;
 
   uinfo("Entry\n");
@@ -2312,7 +2465,11 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
   /* Make sure that we have exclusive access to the private data structure */
 
   DEBUGASSERT(priv);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the keyboard is still connected.  We need to disable interrupts
    * momentarily to assure that there are no asynchronous disconnect events.
@@ -2321,8 +2478,8 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
   if (priv->disconnected)
     {
       /* No... the driver is no longer bound to the class.  That means that
-       * the USB keyboard is no longer connected.  Refuse any further attempts
-       * to access the driver.
+       * the USB keyboard is no longer connected.  Refuse any further
+       * attempts to access the driver.
        */
 
       ret = -ENODEV;
diff --git a/drivers/usbhost/usbhost_hidmouse.c b/drivers/usbhost/usbhost_hidmouse.c
index 9d69019..7df3705 100644
--- a/drivers/usbhost/usbhost_hidmouse.c
+++ b/drivers/usbhost/usbhost_hidmouse.c
@@ -1,35 +1,20 @@
 /****************************************************************************
  * drivers/usbhost/usbhost_hidmouse.c
  *
- *   Copyright (C) 2014, 2015-2017 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -301,7 +286,8 @@ struct usbhost_state_s
 
 /* Semaphores */
 
-static void usbhost_takesem(sem_t *sem);
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Polling support */
@@ -443,9 +429,37 @@ static struct usbhost_state_s *g_priv;    /* Data passed to thread */
  *
  ****************************************************************************/
 
-static void usbhost_takesem(sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -495,7 +509,10 @@ static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
   FAR struct usbhost_state_s *priv;
 
   DEBUGASSERT(!up_interrupt_context());
-  priv = (FAR struct usbhost_state_s *)kmm_malloc(sizeof(struct usbhost_state_s));
+
+  priv = (FAR struct usbhost_state_s *)
+    kmm_malloc(sizeof(struct usbhost_state_s));
+
   uinfo("Allocated: %p\n", priv);
   return priv;
 }
@@ -666,10 +683,10 @@ static void usbhost_notify(FAR struct usbhost_state_s *priv)
       nxsem_post(&priv->waitsem);
     }
 
-  /* If there are threads waiting on poll() for mouse data to become available,
-   * then wake them up now.  NOTE: we wake up all waiting threads because we
-   * do not know that they are going to do.  If they all try to read the data,
-   * then some make end up blocking after all.
+  /* If there are threads waiting on poll() for mouse data to become
+   * available, then wake them up now.  NOTE: we wake up all waiting
+   * threads because we do not know that they are going to do.  If they
+   * all try to read the data, then some make end up blocking after all.
    */
 
   for (i = 0; i < CONFIG_HIDMOUSE_NPOLLWAITERS; i++)
@@ -1030,10 +1047,10 @@ static int usbhost_mouse_poll(int argc, char *argv[])
    * 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 *not* incremented here.  When the driver
-   * structure was created, it was created with a reference count of one.  This
-   * thread is responsible for that count.  The count will be decrement when
-   * this thread exits.
+   * NOTE: that the reference count is *not* incremented here.  When the
+   * driver structure was created, it was created with a reference count of
+   * one.  This thread is responsible for that count.  The count will be
+   * decremented when this thread exits.
    */
 
   priv = g_priv;
@@ -1097,7 +1114,13 @@ static int usbhost_mouse_poll(int argc, char *argv[])
             {
               /* Get exclusive access to the mouse state data */
 
-              usbhost_takesem(&priv->exclsem);
+              ret = usbhost_takesem(&priv->exclsem);
+              if (ret < 0)
+                {
+                  /* Break out and disconnect if the thread is canceled. */
+
+                  break;
+                }
 
               /* Get the HID mouse report */
 
@@ -1165,12 +1188,12 @@ static int usbhost_mouse_poll(int argc, char *argv[])
 
                   usbhost_notify(priv);
                 }
-            }
-        }
 
-      /* Release our lock on the state structure */
+              /* Release our lock on the state structure */
 
-      usbhost_givesem(&priv->exclsem);
+              usbhost_givesem(&priv->exclsem);
+            }
+        }
 
       /* If USB debug is on, then provide some periodic indication that
        * polling is still happening.
@@ -1185,15 +1208,15 @@ static int usbhost_mouse_poll(int argc, char *argv[])
 #endif
     }
 
-  /* We get here when the driver is removed.. or when too many errors have
-   * been encountered.
+  /* We get here when the driver is removed, when too many errors have
+   * been encountered, or the parent thread has been canceled.
    *
    * 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);
+  usbhost_forcetake(&priv->exclsem);
 
   /* Indicate that we are no longer running and decrement the reference
    * count held by this thread.  If there are no other users of the class,
@@ -1370,8 +1393,8 @@ static int usbhost_waitsample(FAR struct usbhost_state_s *priv,
   iinfo("Sampled\n");
 
   /* Re-acquire the semaphore that manages mutually exclusive access to
-   * the device structure.  We may have to wait here.  But we have our sample.
-   * Interrupts and pre-emption will be re-enabled while we wait.
+   * the device structure.  We may have to wait here.  But we have our
+   * sample. Interrupts and pre-emption will be re-enabled while we wait.
    */
 
   ret = nxsem_wait(&priv->exclsem);
@@ -1410,8 +1433,8 @@ errout:
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -1506,14 +1529,16 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_ENDPOINT:
           {
-            FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
 
             uinfo("Endpoint descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
 
             /* Check for an interrupt endpoint. */
 
-            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
+            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_INT)
               {
                 /* Yes.. it is a interrupt endpoint.  IN or OUT? */
 
@@ -1537,11 +1562,13 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the interrupt IN endpoint information */
 
                     epindesc.hport        = hport;
-                    epindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    epindesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
                     epindesc.in           = true;
                     epindesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     epindesc.interval     = epdesc->interval;
-                    epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    epindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
 
                     uinfo("Interrupt IN EP addr:%d mxpacketsize:%d\n",
                           epindesc.addr, epindesc.mxpacketsize);
@@ -1635,25 +1662,32 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
   priv->crefs++;
   DEBUGASSERT(priv->crefs == 2);
 
-  /* 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_HIDMOUSE_STACKSIZE).
+  /* Start a worker task to poll the USB device.  It would be nice to use
+   * 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_HIDMOUSE_STACKSIZE).
    */
 
   uinfo("Start poll task\n");
 
-  /* The inputs to a task started by kthread_create() are very awkward for this
-   * purpose.  They are really designed for command line tasks (argc/argv). So
-   * the following is kludge pass binary data when the mouse poll task
-   * is started.
+  /* The inputs to a task started by kthread_create() are very awkward for
+   * this purpose.  They are really designed for command line tasks
+   * (argc/argv).  So the following is kludge pass binary data when the
+   * mouse 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).
+   * 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);
+  ret = usbhost_takesem(&g_exclsem);
+  if (ret < 0)
+    {
+      usbhost_tdfree(priv);
+      goto errout;
+    }
+
   g_priv = priv;
 
   priv->pollpid = kthread_create("mouse", CONFIG_HIDMOUSE_DEFPRIO,
@@ -1671,9 +1705,14 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 
   /* Now wait for the poll task to get properly initialized */
 
-  usbhost_takesem(&g_syncsem);
+  ret = usbhost_takesem(&g_syncsem);
   usbhost_givesem(&g_exclsem);
 
+  if (ret < 0)
+    {
+      goto errout;
+    }
+
   /* Register the driver */
 
   uinfo("Register driver\n");
@@ -1685,9 +1724,10 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
    */
 
 errout:
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
   priv->crefs--;
   usbhost_givesem(&priv->exclsem);
+
   return ret;
 }
 
@@ -1750,7 +1790,8 @@ static inline uint32_t usbhost_getle32(const uint8_t *val)
 {
   /* Little endian means LS halfword first in byte stream */
 
-  return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
+  return (uint32_t)usbhost_getle16(&val[2]) << 16 |
+         (uint32_t)usbhost_getle16(val);
 }
 
 /****************************************************************************
@@ -1845,12 +1886,13 @@ static inline int usbhost_tdfree(FAR struct usbhost_state_s *priv)
  * Name: usbhost_create
  *
  * Description:
- *   This function implements the create() method of struct usbhost_registry_s.
- *   The create() method is a callback into the class implementation.  It is
- *   used to (1) create a new instance of the USB host class state and to (2)
- *   bind a USB host driver "session" to the class instance.  Use of this
- *   create() method will support environments where there may be multiple
- *   USB ports and multiple USB devices simultaneously connected.
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
  *
  * Input Parameters:
  *   hport - The hub port that manages the new class instance.
@@ -1945,11 +1987,11 @@ static FAR struct usbhost_class_s *
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
- *   NOTE that the class instance remains valid upon return with a failure.  It is
- *   the responsibility of the higher level enumeration logic to call
+ *   NOTE that the class instance remains valid upon return with a failure.
+ *   It is the responsibility of the higher level enumeration logic to call
  *   CLASS_DISCONNECTED to free up the class driver resources.
  *
  * Assumptions:
@@ -1992,8 +2034,9 @@ static int usbhost_connect(FAR struct usbhost_class_s *usbclass,
    * - Failure occurred before the mouse poll task was started successfully.
    *   In this case, the disconnection will have to be handled on the worker
    *   task.
-   * - Failure occurred after the mouse poll task was started successfully.  In
-   *   this case, the disconnection can be performed on the mouse poll thread.
+   * - Failure occurred after the mouse poll task was started successfully.
+   *   In this case, the disconnection can be performed on the mouse poll
+   *   thread.
    */
 
   return ret;
@@ -2049,8 +2092,9 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
    * - Failure occurred before the mouse poll task was started successfully.
    *   In this case, the disconnection will have to be handled on the worker
    *   task.
-   * - Failure occurred after the mouse poll task was started successfully.  In
-   *   this case, the disconnection can be performed on the mouse poll thread.
+   * - Failure occurred after the mouse poll task was started successfully.
+   *   In this case, the disconnection can be performed on the mouse poll
+   *   thread.
    */
 
   if (priv->polling)
@@ -2104,11 +2148,15 @@ static int usbhost_open(FAR struct file *filep)
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the mouse device is still connected.  We need to disable
-   * interrupts momentarily to assure that there are no asynchronous disconnect
-   * events.
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   flags = enter_critical_section();
@@ -2170,6 +2218,7 @@ static int usbhost_close(FAR struct file *filep)
   FAR struct inode *inode;
   FAR struct usbhost_state_s *priv;
   irqstate_t flags;
+  int ret;
 
   uinfo("Entry\n");
   DEBUGASSERT(filep && filep->f_inode);
@@ -2179,7 +2228,11 @@ static int usbhost_close(FAR struct file *filep)
   /* Decrement the reference count on the driver */
 
   DEBUGASSERT(priv->crefs >= 1);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* We need to disable interrupts momentarily to assure that there are no
    * asynchronous poll or disconnect events.
@@ -2200,9 +2253,9 @@ static int usbhost_close(FAR struct file *filep)
        *
        * 1) It might be zero meaning that the polling thread has already
        *    exited and decremented its count.
-       * 2) If might be one meaning either that (a) the polling thread is still
-       *    running and still holds a count, or (b) the polling thread has exited,
-       *    but there is still an outstanding open reference.
+       * 2) If might be one meaning either that (a) the polling thread is
+       *    still running and still holds a count, or (b) the polling thread
+       *    has exited, but there is still an outstanding open reference.
        */
 
       if (priv->crefs == 0 || (priv->crefs == 1 && priv->polling))
@@ -2255,7 +2308,8 @@ 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_read(FAR struct file *filep, FAR char *buffer,
+                            size_t len)
 {
   FAR struct inode           *inode;
   FAR struct usbhost_state_s *priv;
@@ -2275,7 +2329,11 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the mouse is still connected.  We need to disable interrupts
    * momentarily to assure that there are no asynchronous disconnect events.
@@ -2344,7 +2402,8 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
 
       if (sample.valid)
         {
-          report->point[0].flags  = TOUCH_UP | TOUCH_ID_VALID | TOUCH_POS_VALID;
+          report->point[0].flags  = TOUCH_UP | TOUCH_ID_VALID |
+                                    TOUCH_POS_VALID;
         }
       else
         {
@@ -2355,13 +2414,15 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
     {
       /* First event */
 
-      report->point[0].flags  = TOUCH_DOWN | TOUCH_ID_VALID | TOUCH_POS_VALID;
+      report->point[0].flags  = TOUCH_DOWN | TOUCH_ID_VALID |
+                                TOUCH_POS_VALID;
     }
   else /* if (sample->event == BUTTON_MOVE) */
     {
       /* Movement of the same event */
 
-      report->point[0].flags  = TOUCH_MOVE | TOUCH_ID_VALID | TOUCH_POS_VALID;
+      report->point[0].flags  = TOUCH_MOVE | TOUCH_ID_VALID |
+                                TOUCH_POS_VALID;
     }
 
   iinfo("  id:      %d\n", report->point[0].id);
@@ -2419,7 +2480,7 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
 {
   FAR struct inode           *inode;
   FAR struct usbhost_state_s *priv;
-  int                         ret = OK;
+  int                         ret;
   int                         i;
 
   uinfo("Entry\n");
@@ -2430,7 +2491,11 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
   /* Make sure that we have exclusive access to the private data structure */
 
   DEBUGASSERT(priv);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the mouse is still connected.  We need to disable interrupts
    * momentarily to assure that there are no asynchronous disconnect events.
diff --git a/drivers/usbhost/usbhost_max3421e.c b/drivers/usbhost/usbhost_max3421e.c
index cdb2aca..e322bfd 100644
--- a/drivers/usbhost/usbhost_max3421e.c
+++ b/drivers/usbhost/usbhost_max3421e.c
@@ -1,43 +1,29 @@
 /****************************************************************************
  * drivers/usbhost/usbhost_max3421e.c
  *
- *   Copyright (C) 2018, 2019 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
  *
- * References:
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/* References:
  *   "MAX3421E USB Peripheral/Host Controller with SPI Interface",
  *      19-3953, Rev 4, Maxim Integrated, July 2013 (Datasheet).
  *   "MAX3421E Programming Guide", Maxim Integrated, December 2006
  *      (Application Note).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
+ */
 
 /****************************************************************************
  * Included Files
@@ -74,7 +60,9 @@
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
-/* Configuration ***************************************************************/
+
+/* Configuration ************************************************************/
+
 /* MAX3421E USB Host Driver Support
  *
  * Pre-requisites
@@ -114,13 +102,13 @@
 #  undef CONFIG_MAX3421E_USBHOST_PKTDUMP
 #endif
 
-/* Delays **********************************************************************/
+/* Delays *******************************************************************/
 
-#define MAX3421E_READY_DELAY         200000 /* In loop counts */
-#define MAX3421E_FLUSH_DELAY         200000 /* In loop counts */
+#define MAX3421E_READY_DELAY         200000      /* In loop counts */
+#define MAX3421E_FLUSH_DELAY         200000      /* In loop counts */
 #define MAX3421E_SETUP_DELAY         SEC2TICK(5) /* 5 seconds in system ticks */
 #define MAX3421E_DATANAK_DELAY       SEC2TICK(5) /* 5 seconds in system ticks */
-#define MAX3421E_RETRY_COUNT         5      /* Number of tries before giving up */
+#define MAX3421E_RETRY_COUNT         5           /* Number of tries before giving up */
 
 /* Ever-present MIN/MAX macros */
 
@@ -220,7 +208,7 @@ struct max3421e_usbhost_s
   uint8_t           xfrtype;   /* See enum mx3421e_hxfrdn_e */
   uint8_t           inflight;  /* Number of Tx bytes "in-flight" (<= 128) */
   uint8_t           result;    /* The result of the transfer */
-  uint8_t           exclcount;  /* Number of nested exclem locks */
+  uint8_t           exclcount; /* Number of nested exclem locks */
   uint16_t          buflen;    /* Buffer length (at start of transfer) */
   uint16_t          xfrd;      /* Bytes transferred (at end of transfer) */
   pid_t             holder;    /* Current hold of the exclsem */
@@ -424,18 +412,18 @@ static void max3421e_sndblock(FAR struct max3421e_usbhost_s *priv,
 #  define max3421e_pktdump(m,b,n)
 #endif
 
-/* Semaphores ******************************************************************/
+/* Semaphores ***************************************************************/
 
-static void max3421e_takesem(sem_t *sem);
+static int max3421e_takesem(FAR sem_t *sem);
 #define max3421e_givesem(s) nxsem_post(s);
-static void max3421e_take_exclsem(FAR struct max3421e_usbhost_s *priv);
+static int max3421e_take_exclsem(FAR struct max3421e_usbhost_s *priv);
 static void max3421e_give_exclsem(FAR struct max3421e_usbhost_s *priv);
 
-/* Byte stream access helper functions *****************************************/
+/* Byte stream access helper functions **************************************/
 
 static inline uint16_t max3421e_getle16(const uint8_t *val);
 
-/* Channel management **********************************************************/
+/* Channel management *******************************************************/
 
 static int max3421e_chan_alloc(FAR struct max3421e_usbhost_s *priv);
 static inline void max3421e_chan_free(FAR struct max3421e_usbhost_s *priv,
@@ -452,11 +440,12 @@ static int max3421e_chan_wait(FAR struct max3421e_usbhost_s *priv,
 static void max3421e_chan_wakeup(FAR struct max3421e_usbhost_s *priv,
               FAR struct max3421e_chan_s *chan, int result);
 
-/* Control/data transfer logic *************************************************/
+/* Control/data transfer logic **********************************************/
 
 static inline void max3421e_save_toggles(FAR struct max3421e_usbhost_s *priv,
               FAR struct max3421e_chan_s *chan);
-static inline void max3421e_restore_toggles(FAR struct max3421e_usbhost_s *priv,
+static inline void max3421e_restore_toggles(
+              FAR struct max3421e_usbhost_s *priv,
               FAR struct max3421e_chan_s *chan);
 static int  max3421e_transfer_status(FAR struct max3421e_usbhost_s *priv);
 static void max3421e_transfer_terminate(FAR struct max3421e_usbhost_s *priv,
@@ -475,9 +464,9 @@ static ssize_t max3421e_out_transfer(FAR struct max3421e_usbhost_s *priv,
 #ifdef CONFIG_USBHOST_ASYNCH
 static void max3421e_out_next(FAR struct max3421e_usbhost_s *priv,
               FAR struct max3421e_chan_s *chan);
-static int  max3421e_out_asynch(FAR struct max3421e_usbhost_s *priv, int chidx,
-              FAR uint8_t *buffer, size_t buflen, usbhost_asynch_t callback,
-              FAR void *arg);
+static int  max3421e_out_asynch(FAR struct max3421e_usbhost_s *priv,
+              FAR struct max3421e_chan_s *chan, FAR uint8_t *buffer,
+              size_t buflen, usbhost_asynch_t callback, FAR void *arg);
 #endif
 
 /* Control transfers */
@@ -517,7 +506,7 @@ static int  max3421e_in_asynch(FAR struct max3421e_usbhost_s *priv,
               size_t buflen, usbhost_asynch_t callback, FAR void *arg);
 #endif
 
-/* Interrupt handling **********************************************************/
+/* Interrupt handling *******************************************************/
 
 static void max3421e_connect_event(FAR struct max3421e_usbhost_s *priv);
 static void max3421e_disconnect_event(FAR struct max3421e_usbhost_s *priv);
@@ -532,13 +521,14 @@ static inline void max3421e_int_enable(FAR struct max3421e_usbhost_s *priv,
               uint8_t irqset);
 static inline void max3421e_int_disable(FAR struct max3421e_usbhost_s *priv,
               uint8_t irqset);
-static inline uint8_t max3421e_int_status(FAR struct max3421e_usbhost_s *priv);
+static inline uint8_t max3421e_int_status(
+              FAR struct max3421e_usbhost_s *priv);
 static inline void max3421e_int_clear(FAR struct max3421e_usbhost_s *priv,
               uint8_t irqset);
 static void max3421e_int_wait(FAR struct max3421e_usbhost_s *priv,
               uint8_t irqset, unsigned int usec);
 
-/* USB host controller operations **********************************************/
+/* USB host controller operations *******************************************/
 
 static int  max3421e_wait(FAR struct usbhost_connection_s *conn,
               FAR struct usbhost_hubport_s **hport);
@@ -552,26 +542,33 @@ static int  max3421e_ep0configure(FAR struct usbhost_driver_s *drvr,
               usbhost_ep_t ep0, uint8_t funcaddr, uint8_t speed,
               uint16_t maxpacketsize);
 static int  max3421e_epalloc(FAR struct usbhost_driver_s *drvr,
-              FAR const FAR struct usbhost_epdesc_s *epdesc, FAR usbhost_ep_t *ep);
-static int  max3421e_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
+              FAR const FAR struct usbhost_epdesc_s *epdesc,
+              FAR usbhost_ep_t *ep);
+static int  max3421e_epfree(FAR struct usbhost_driver_s *drvr,
+              usbhost_ep_t ep);
 static int  max3421e_alloc(FAR struct usbhost_driver_s *drvr,
               FAR uint8_t **buffer, FAR size_t *maxlen);
-static int  max3421e_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
+static int  max3421e_free(FAR struct usbhost_driver_s *drvr,
+              FAR uint8_t *buffer);
 static int  max3421e_ioalloc(FAR struct usbhost_driver_s *drvr,
               FAR uint8_t **buffer, size_t buflen);
-static int  max3421e_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer);
-static int  max3421e_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
-              FAR const struct usb_ctrlreq_s *req, FAR uint8_t *buffer);
-static int  max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
-              FAR const struct usb_ctrlreq_s *req, FAR const uint8_t *buffer);
-static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
-              FAR uint8_t *buffer, size_t buflen);
+static int  max3421e_iofree(FAR struct usbhost_driver_s *drvr,
+              FAR uint8_t *buffer);
+static int  max3421e_ctrlin(FAR struct usbhost_driver_s *drvr,
+              usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req,
+              FAR uint8_t *buffer);
+static int  max3421e_ctrlout(FAR struct usbhost_driver_s *drvr,
+              usbhost_ep_t ep0, FAR const struct usb_ctrlreq_s *req,
+              FAR const uint8_t *buffer);
+static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr,
+              usbhost_ep_t ep, FAR uint8_t *buffer, size_t buflen);
 #ifdef CONFIG_USBHOST_ASYNCH
-static int  max3421e_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
-              FAR uint8_t *buffer, size_t buflen, usbhost_asynch_t callback,
-              FAR void *arg);
+static int  max3421e_asynch(FAR struct usbhost_driver_s *drvr,
+              usbhost_ep_t ep, FAR uint8_t *buffer, size_t buflen,
+              usbhost_asynch_t callback, FAR void *arg);
 #endif
-static int  max3421e_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep);
+static int  max3421e_cancel(FAR struct usbhost_driver_s *drvr,
+                            usbhost_ep_t ep);
 #ifdef CONFIG_USBHOST_HUB
 static int  max3421e_connect(FAR struct max3421e_usbhost_s *priv,
               FAR struct usbhost_hubport_s *hport, bool connected);
@@ -587,7 +584,8 @@ static int  max3421e_startsof(FAR struct max3421e_usbhost_s *priv);
 static inline int max3421e_sw_initialize(FAR struct max3421e_usbhost_s *priv,
               FAR struct max3421e_connection_s *conn,
               FAR const struct max3421e_lowerhalf_s *lower);
-static inline int max3421e_hw_initialize(FAR struct max3421e_usbhost_s *priv);
+static inline int max3421e_hw_initialize(
+              FAR struct max3421e_usbhost_s *priv);
 
 /****************************************************************************
  * Private Data
@@ -598,59 +596,101 @@ static inline int max3421e_hw_initialize(FAR struct max3421e_usbhost_s *priv);
 
 static const struct max3421e_usbhost_trace_s g_trace1[TRACE1_NSTRINGS] =
 {
-  TRENTRY(MAX3421E_TRACE1_ALLOC_FAIL,        TR_FMT1, "INIT: Failed to allocate state structure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_ALLOC_FAIL, TR_FMT1,
+          "INIT: Failed to allocate state structure: %u\n"),
 #ifdef CONFIG_USBHOST_ASYNCH
-  TRENTRY(MAX3421E_TRACE1_ASYNCHSETUP_FAIL1, TR_FMT1, "OUT: Asynch setup failed: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_ASYNCHSETUP_FAIL2, TR_FMT1, "IN: Asynch setup failed: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_ASYNCHSETUP_FAIL1, TR_FMT1,
+          "OUT: Asynch setup failed: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_ASYNCHSETUP_FAIL2, TR_FMT1,
+          "IN: Asynch setup failed: %u\n"),
 #endif
-  TRENTRY(MAX3421E_TRACE1_BAD_JKSTATE,       TR_FMT1, "CONNECT: Bad JK state: %02x\n"),
-  TRENTRY(MAX3421E_TRACE1_BADREVISION,       TR_FMT1, "INIT: Bad revision number:  %02x\n"),
-  TRENTRY(MAX3421E_TRACE1_CHANALLOC_FAIL,    TR_FMT1, "EPALLOC: Channel allocation failed: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_CHANWAIT_FAIL,     TR_FMT1, "OUT: Channel wait failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN1,       TR_FMT1, "OUT: Disconnected during wait: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN2,       TR_FMT1, "CTRL: Disconnected during SETUP phase: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN3,       TR_FMT1, "CTRL OUT: Disconnected during DATA phase: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN4,       TR_FMT1, "CTRL IN: Disconnected during DATA phase: %u"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN5,       TR_FMT1, "IN: Disconnected during wait: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN6,       TR_FMT1, "CONNECT: Device disconnect #1: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN7,       TR_FMT1, "CONNECT: Device disconnect #2: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_DEVDISCONN8,       TR_FMT1, "CONNECT: Device disconnect #3: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_ENUMERATE_FAIL,    TR_FMT1, "CONNECT: Enumeration failed: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL1,     TR_FMT1, "CTRL IN: SETUP phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_BAD_JKSTATE, TR_FMT1,
+          "CONNECT: Bad JK state: %02x\n"),
+  TRENTRY(MAX3421E_TRACE1_BADREVISION, TR_FMT1,
+          "INIT: Bad revision number:  %02x\n"),
+  TRENTRY(MAX3421E_TRACE1_CHANALLOC_FAIL, TR_FMT1,
+          "EPALLOC: Channel allocation failed: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_CHANWAIT_FAIL, TR_FMT1,
+          "OUT: Channel wait failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN1, TR_FMT1,
+          "OUT: Disconnected during wait: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN2, TR_FMT1,
+          "CTRL: Disconnected during SETUP phase: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN3, TR_FMT1,
+          "CTRL OUT: Disconnected during DATA phase: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN4, TR_FMT1,
+          "CTRL IN: Disconnected during DATA phase: %u"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN5, TR_FMT1,
+          "IN: Disconnected during wait: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN6, TR_FMT1,
+          "CONNECT: Device disconnect #1: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN7, TR_FMT1,
+          "CONNECT: Device disconnect #2: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_DEVDISCONN8, TR_FMT1,
+          "CONNECT: Device disconnect #3: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_ENUMERATE_FAIL, TR_FMT1,
+          "CONNECT: Enumeration failed: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL1, TR_FMT1,
+          "CTRL IN: SETUP phase failure: %u\n"),
 #ifdef CONFIG_USBHOST_ASYNCH
-  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL2,     TR_FMT1, "CTRL IN: Asynch SETUP phase failure #1: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL3,     TR_FMT1, "CTRL IN: Asynch SETUP phase failure #2: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL2, TR_FMT1,
+          "CTRL IN: Asynch SETUP phase failure #1: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_INSETUP_FAIL3, TR_FMT1,
+          "CTRL IN: Asynch SETUP phase failure #2: %u\n"),
 #endif
-  TRENTRY(MAX3421E_TRACE1_IRQATTACH_FAIL,    TR_FMT1, "INIT: Failed to attach interrupt: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL1,    TR_FMT1, "CTRL OUT: SETUP phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_IRQATTACH_FAIL, TR_FMT1,
+          "INIT: Failed to attach interrupt: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL1, TR_FMT1,
+          "CTRL OUT: SETUP phase failure: %u\n"),
 #ifdef CONFIG_USBHOST_ASYNCH
-  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL2,    TR_FMT1, "CTRL OUT: Asynch SETUP phase failure #1: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL3,    TR_FMT1, "CTRL OUT: Asynch SETUP phase failure #2: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL2, TR_FMT1,
+          "CTRL OUT: Asynch SETUP phase failure #1: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_OUTSETUP_FAIL3, TR_FMT1,
+          "CTRL OUT: Asynch SETUP phase failure #2: %u\n"),
 #endif
-  TRENTRY(MAX3421E_TRACE1_RECVDATA_FAIL,     TR_FMT1, "CTRL IN: Data phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_RECVSTATUS_FAIL,   TR_FMT1, "CTRL OUT: Status phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_SENDDATA_FAIL,     TR_FMT1, "CTRL OUT: Data phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_SENDSETUP_FAIL1,   TR_FMT1, "CTRL OUT: SETUP phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_SENDSETUP_FAIL2,   TR_FMT1, "CTRL IN: SETUP phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_SENDSTATUS_FAIL,   TR_FMT1, "CTRL IN: Status phase failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED1,  TR_FMT1, "OUT: Transfer wait returned failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED2,  TR_FMT1, "CTRL: SETUP wait returned failure: %u\n"),
-  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED3,  TR_FMT1, "IN: Transfer wait returned failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_RECVDATA_FAIL, TR_FMT1,
+          "CTRL IN: Data phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_RECVSTATUS_FAIL, TR_FMT1,
+          "CTRL OUT: Status phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_SENDDATA_FAIL, TR_FMT1,
+          "CTRL OUT: Data phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_SENDSETUP_FAIL1, TR_FMT1,
+          "CTRL OUT: SETUP phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_SENDSETUP_FAIL2, TR_FMT1,
+          "CTRL IN: SETUP phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_SENDSTATUS_FAIL, TR_FMT1,
+          "CTRL IN: Status phase failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED1, TR_FMT1,
+          "OUT: Transfer wait returned failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED2, TR_FMT1,
+          "CTRL: SETUP wait returned failure: %u\n"),
+  TRENTRY(MAX3421E_TRACE1_TRANSFER_FAILED3, TR_FMT1,
+          "IN: Transfer wait returned failure: %u\n"),
 
 #ifdef HAVE_USBHOST_TRACE_VERBOSE
-  TRENTRY(MAX3421E_VTRACE1_CANCEL,           TR_FMT1, "Transfer canceled: EP%u\n"),
-  TRENTRY(MAX3421E_VTRACE1_CONNECTED1,       TR_FMT1, "CONNECT: Connection event: %u\n"),
-  TRENTRY(MAX3421E_VTRACE1_CONNECTED2,       TR_FMT1, "CONNECT: Connection change detected: %u\n"),
-  TRENTRY(MAX3421E_VTRACE1_CONNECTED3,       TR_FMT1, "CONNECT: Connected: %u\n"),
-  TRENTRY(MAX3421E_VTRACE1_DISCONNECTED1,    TR_FMT1, "CONNECT: Disconnected: %u\n"),
-  TRENTRY(MAX3421E_VTRACE1_DISCONNECTED2,    TR_FMT1, "CONNECT: Disconnect detected: %u\n"),
-  TRENTRY(MAX3421E_VTRACE1_ENUMERATE,        TR_FMT1, "ENUMERATE: Start: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_CANCEL, TR_FMT1,
+          "Transfer canceled: EP%u\n"),
+  TRENTRY(MAX3421E_VTRACE1_CONNECTED1, TR_FMT1,
+          "CONNECT: Connection event: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_CONNECTED2, TR_FMT1,
+          "CONNECT: Connection change detected: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_CONNECTED3, TR_FMT1,
+          "CONNECT: Connected: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_DISCONNECTED1, TR_FMT1,
+          "CONNECT: Disconnected: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_DISCONNECTED2, TR_FMT1,
+          "CONNECT: Disconnect detected: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_ENUMERATE, TR_FMT1,
+          "ENUMERATE: Start: %u\n"),
 #ifdef CONFIG_USBHOST_HUB
-  TRENTRY(MAX3421E_VTRACE1_HUB_CONNECTED,    TR_FMT1, "CONNECT: Hub connected: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_HUB_CONNECTED, TR_FMT1,
+          "CONNECT: Hub connected: %u\n"),
 #endif
-  TRENTRY(MAX3421E_VTRACE1_INITIALIZED,      TR_FMT1, "INIT: Hardware initialized: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_INITIALIZED, TR_FMT1,
+          "INIT: Hardware initialized: %u\n"),
 #ifdef CONFIG_USBHOST_ASYNCH
- TRENTRY(MAX3421E_VTRACE1_TRANSFER_COMPLETE, TR_FMT1, "OUT: Asynch transfer complete: %u\n"),
+  TRENTRY(MAX3421E_VTRACE1_TRANSFER_COMPLETE, TR_FMT1,
+          "OUT: Asynch transfer complete: %u\n"),
 #endif
 #endif
 };
@@ -659,28 +699,46 @@ static const struct max3421e_usbhost_trace_s g_trace2[TRACE2_NSTRINGS] =
 {
 #ifdef HAVE_USBHOST_TRACE_VERBOSE
 #ifdef CONFIG_USBHOST_ASYNCH
-  TRENTRY(MAX3421E_VTRACE2_ASYNCH,           TR_FMT2, "ASYNCH: Transfer started: EP%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_ASYNCH, TR_FMT2,
+          "ASYNCH: Transfer started: EP%u len=%u\n"),
 #endif
-  TRENTRY(MAX3421E_VTRACE2_BULKIN,           TR_FMT2, "BULK IN:  SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_BULKOUT,          TR_FMT2, "BULK OUT:  SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_CHANWAKEUP_IN,    TR_FMT2, "IN: Channel wakeup: Chan%, result=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_CHANWAKEUP_OUT,   TR_FMT2, "OUT: Channel wakeup: Chan%u result=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_CTRLIN,           TR_FMT2, "CTRL IN: Start: type=%u req=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_CTRLOUT,          TR_FMT2, "CTRL OUT: Start: type=%u req=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_BULKIN, TR_FMT2,
+          "BULK IN:  SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_BULKOUT, TR_FMT2,
+          "BULK OUT:  SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_CHANWAKEUP_IN, TR_FMT2,
+          "IN: Channel wakeup: Chan%, result=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_CHANWAKEUP_OUT, TR_FMT2,
+          "OUT: Channel wakeup: Chan%u result=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_CTRLIN, TR_FMT2,
+          "CTRL IN: Start: type=%u req=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_CTRLOUT, TR_FMT2,
+          "CTRL OUT: Start: type=%u req=%u\n"),
 #ifdef CONFIG_USBHOST_HUB
-  TRENTRY(MAX3421E_VTRACE2_HUB_CONNECTED,    TR_FMT2, "CONNECT: Hub connected: port=%u, connected=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_HUB_CONNECTED, TR_FMT2,
+          "CONNECT: Hub connected: port=%u, connected=%u\n"),
 #endif
-  TRENTRY(MAX3421E_VTRACE2_INTRIN,           TR_FMT2, "INTR IN: SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_INTROUT,          TR_FMT2, "INTR OUT: SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_ISOCIN,           TR_FMT2, "ISOC IN: SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_ISOCOUT,          TR_FMT2, "ISOC OUT: SETUP: Chan%u len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_RECVSTATUS,       TR_FMT2, "CTRL OUT: Receive status: Chan% len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_SENDSTATUS,       TR_FMT2, "CTRL IN: Send status: Chan% len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_STARTTRANSFER1,   TR_FMT2, "OUT: Send start: Chan% len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_STARTTRANSFER2,   TR_FMT2, "IN: Receive start: Chan% len=%u\n"),
-  TRENTRY(MAX3421E_VTRACE2_TRANSFER,         TR_FMT2, "Transfer start: EP%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_INTRIN, TR_FMT2,
+          "INTR IN: SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_INTROUT, TR_FMT2,
+          "INTR OUT: SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_ISOCIN, TR_FMT2,
+          "ISOC IN: SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_ISOCOUT, TR_FMT2,
+          "ISOC OUT: SETUP: Chan%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_RECVSTATUS, TR_FMT2,
+          "CTRL OUT: Receive status: Chan% len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_SENDSTATUS, TR_FMT2,
+          "CTRL IN: Send status: Chan% len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_STARTTRANSFER1, TR_FMT2,
+          "OUT: Send start: Chan% len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_STARTTRANSFER2, TR_FMT2,
+          "IN: Receive start: Chan% len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_TRANSFER, TR_FMT2,
+          "Transfer start: EP%u len=%u\n"),
 #ifdef CONFIG_USBHOST_ASYNCH
-  TRENTRY(MAX3421E_VTRACE2_XFRCOMPLETE,      TR_FMT2, "ASYNCH: Transfer complete: EP%u len=%u\n"),
+  TRENTRY(MAX3421E_VTRACE2_XFRCOMPLETE, TR_FMT2,
+          "ASYNCH: Transfer complete: EP%u len=%u\n"),
 #endif
 #endif
 };
@@ -772,8 +830,8 @@ static void max3421e_checkreg(uint8_t addr, uint8_t val, bool iswrite)
   static unsigned int count = 0;
   static bool prevwrite = false;
 
-  /* Is this the same value that we read from/wrote to the same register last time?
-   * Are we polling the register?  If so, suppress the output.
+  /* Is this the same value that we read from/wrote to the same register
+   * last time?  Are we polling the register?  If so, suppress the output.
    */
 
   if (addr == prevaddr && val == preval && prevwrite == iswrite)
@@ -974,7 +1032,6 @@ static inline void max3421e_modifyreg(FAR struct max3421e_usbhost_s *priv,
 static void max3421e_recvblock(FAR struct max3421e_usbhost_s *priv,
                                uint8_t addr, FAR void *buffer, size_t buflen)
 {
-
   FAR const struct max3421e_lowerhalf_s *lower = priv->lower;
   FAR struct spi_dev_s *spi;
   uint8_t cmd;
@@ -1061,9 +1118,9 @@ static void max3421e_sndblock(FAR struct max3421e_usbhost_s *priv,
  *
  ****************************************************************************/
 
-static void max3421e_takesem(sem_t *sem)
+static int max3421e_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
 }
 
 /****************************************************************************
@@ -1074,45 +1131,52 @@ static void max3421e_takesem(sem_t *sem)
  *
  ****************************************************************************/
 
-static void max3421e_take_exclsem(FAR struct max3421e_usbhost_s *priv)
+static int max3421e_take_exclsem(FAR struct max3421e_usbhost_s *priv)
 {
   pid_t me = getpid();
+  int ret = OK;
 
   /* Does this thread already hold the mutual exclusion mutex? */
 
   if (priv->holder == me)
     {
-       /* Yes.. just increment the count */
+      /* Yes.. just increment the count */
 
-       DEBUGASSERT(priv->exclcount < UINT8_MAX);
-       priv->exclcount++;
+      DEBUGASSERT(priv->exclcount < UINT8_MAX);
+      priv->exclcount++;
     }
   else
     {
       /* No.. take the semaphore */
 
-      max3421e_takesem(&priv->exclsem);
-
-      /* Now this thread is the holder with a count of one */
+      ret = max3421e_takesem(&priv->exclsem);
+      if (ret >= 0)
+        {
+          /* Now this thread is the holder with a count of one */
 
-      priv->holder = me;
-      priv->exclcount = 1;
+          priv->holder = me;
+          priv->exclcount = 1;
+        }
     }
+
+  return ret;
 }
 
 static void max3421e_give_exclsem(FAR struct max3421e_usbhost_s *priv)
 {
+#ifdef CONFIG_DEBUG_ASSERTIONS
   pid_t me = getpid();
 
   DEBUGASSERT(priv->holder == me);
+#endif
 
   /* Is the lock nested? */
 
   if (priv->exclcount > 0)
     {
-       /* Yes.. just decrement the count */
+      /* Yes.. just decrement the count */
 
-       priv->exclcount--;
+      priv->exclcount--;
     }
   else
     {
@@ -1177,7 +1241,8 @@ static int max3421e_chan_alloc(FAR struct max3421e_usbhost_s *priv)
  *
  ****************************************************************************/
 
-static void max3421e_chan_free(FAR struct max3421e_usbhost_s *priv, int chidx)
+static void max3421e_chan_free(FAR struct max3421e_usbhost_s *priv,
+                               int chidx)
 {
   DEBUGASSERT((unsigned)chidx < MAX3421E_NHOST_CHANNELS);
 
@@ -1193,13 +1258,14 @@ static void max3421e_chan_free(FAR struct max3421e_usbhost_s *priv, int chidx)
  * Name: max3421e_chan_waitsetup
  *
  * Description:
- *   Set the request for the transfer complete event well BEFORE enabling the
- *   transfer (as soon as we are absolutely committed to the to avoid transfer).
- *   We do this to minimize race conditions.  This logic would have to be expanded
- *   if we want to have more than one packet in flight at a time!
+ *   Set the request for the transfer complete event well BEFORE enabling
+ *   the transfer (as soon as we are absolutely committed to the transfer).
+ *   We do this to minimize race conditions.  This logic would have to be
+ *   expanded if we want to have more than one packet in flight at a time!
  *
  * Assumptions:
- *   Called from a normal thread context BEFORE the transfer has been started.
+ *   Called from a normal thread context BEFORE the transfer has been
+ *   started.
  *
  ****************************************************************************/
 
@@ -1215,8 +1281,9 @@ static int max3421e_chan_waitsetup(FAR struct max3421e_usbhost_s *priv,
 
   if (priv->connected)
     {
-      /* Yes.. then set waiter to indicate that we expect to be informed when
-       * either (1) the device is disconnected, or (2) the transfer completed.
+      /* Yes.. then set waiter to indicate that we expect to be informed
+       * when either (1) the device is disconnected, or (2) the transfer
+       * completed.
        */
 
       priv->waiter   = chan;
@@ -1236,8 +1303,8 @@ static int max3421e_chan_waitsetup(FAR struct max3421e_usbhost_s *priv,
  *
  * Description:
  *   Set the request for the transfer complete event well BEFORE enabling the
- *   transfer (as soon as we are absolutely committed to the to avoid transfer).
- *   We do this to minimize race conditions.  This logic would have to be expanded
+ *   transfer (as soon as we are absolutely committed to transfer).  We do
+ *   this to minimize race conditions.  This logic would have to be expanded
  *   if we want to have more than one packet in flight at a time!
  *
  * Assumptions:
@@ -1288,9 +1355,9 @@ static int max3421e_chan_wait(FAR struct max3421e_usbhost_s *priv,
   int ret;
 
   /* Disable interrupts so that the following operations will be atomic.  On
-   * the host global interrupt needs to be disabled.  However, here we disable
-   * all interrupts to exploit that fact that interrupts will be re-enabled
-   * while we wait.
+   * the host global interrupt needs to be disabled.  However, here we
+   * disable all interrupts to exploit that fact that interrupts will be re-
+   * enabled while we wait.
    */
 
   flags = enter_critical_section();
@@ -1308,7 +1375,11 @@ static int max3421e_chan_wait(FAR struct max3421e_usbhost_s *priv,
        * wait here.
        */
 
-      nxsem_wait_uninterruptible(&priv->waitsem);
+      ret = nxsem_wait_uninterruptible(&priv->waitsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
     }
   while (priv->waiter != NULL);
 
@@ -1389,14 +1460,16 @@ static void max3421e_chan_wakeup(FAR struct max3421e_usbhost_s *priv,
  *
  ****************************************************************************/
 
-static inline void max3421e_save_toggles(FAR struct max3421e_usbhost_s *priv,
-              FAR struct max3421e_chan_s *chan)
+static inline void
+  max3421e_save_toggles(FAR struct max3421e_usbhost_s *priv,
+                       FAR struct max3421e_chan_s *chan)
 {
   chan->toggles = max3421e_getreg(priv, MAX3421E_USBHOST_HCTL);
 }
 
-static inline void max3421e_restore_toggles(FAR struct max3421e_usbhost_s *priv,
-              FAR struct max3421e_chan_s *chan)
+static inline void
+  max3421e_restore_toggles(FAR struct max3421e_usbhost_s *priv,
+                           FAR struct max3421e_chan_s *chan)
 {
   max3421e_modifyreg(priv, MAX3421E_USBHOST_HCTL,
                      USBHOST_HCTL_TOGGLES_MASK,
@@ -1486,25 +1559,25 @@ static void max3421e_transfer_terminate(FAR struct max3421e_usbhost_s *priv,
                                         FAR struct max3421e_chan_s *chan,
                                         int result)
 {
-   /* Disable further SNDBAV, RCVDAV or HXFRDN interrupts */
+  /* Disable further SNDBAV, RCVDAV or HXFRDN interrupts */
 
-   max3421e_int_disable(priv, USBHOST_HIRQ_SNDBAVIRQ |
-                              USBHOST_HIRQ_RCVDAVIRQ |
-                              USBHOST_HIRQ_HXFRDNIRQ);
+  max3421e_int_disable(priv, USBHOST_HIRQ_SNDBAVIRQ |
+                             USBHOST_HIRQ_RCVDAVIRQ |
+                             USBHOST_HIRQ_HXFRDNIRQ);
 
-   /* Save the endpoint toggle settings.
-    *
-    * REVISIT:  The MAX4321E sends fixed DATA0 and DATA1 PID tokens for the
-    * various stages of a CONTROL transfer, regardless of the setting of
-    * the internal data toggle.
-    */
+  /* Save the endpoint toggle settings.
+   *
+   * REVISIT:  The MAX4321E sends fixed DATA0 and DATA1 PID tokens for the
+   * various stages of a CONTROL transfer, regardless of the setting of
+   * the internal data toggle.
+   */
 
-   max3421e_save_toggles(priv, chan);
+  max3421e_save_toggles(priv, chan);
 
-   /* Wake up any waiters for the end of transfer event */
+  /* Wake up any waiters for the end of transfer event */
 
-   DEBUGASSERT(priv->waiter != NULL);
-   max3421e_chan_wakeup(priv, chan, -result);
+  DEBUGASSERT(priv->waiter != NULL);
+  max3421e_chan_wakeup(priv, chan, -result);
 }
 
 /****************************************************************************
@@ -1551,7 +1624,7 @@ static void max3421e_put_sndfifo(FAR struct max3421e_usbhost_s *priv,
 
   for (i = 0;
        i < 2 && committed < priv->buflen &&
-       (max3421e_int_status(priv) & USBHOST_HIRQ_SNDBAVIRQ) == 1;
+       (max3421e_int_status(priv) & USBHOST_HIRQ_SNDBAVIRQ) != 0;
        i++)
     {
       /* Get the size of the biggest thing that we can put in the current
@@ -1727,7 +1800,7 @@ static void max3421e_send_start(FAR struct max3421e_usbhost_s *priv,
 
       max3421e_restore_toggles(priv, chan);
 
-      /* Then load the data into the SNDFIFO and start the transfer*/
+      /* Then load the data into the SNDFIFO and start the transfer */
 
       max3421e_put_sndfifo(priv, chan);
     }
@@ -1840,11 +1913,11 @@ static ssize_t max3421e_out_transfer(FAR struct max3421e_usbhost_s *priv,
               return (ssize_t)ret;
             }
 
-          /* Get the device a little time to catch up.  Then retry the transfer
-           * using the same buffer pointer and length.
+          /* Get the device a little time to catch up.  Then retry the
+           * transfer using the same buffer pointer and length.
            */
 
-          nxsig_usleep(20*1000);
+          nxsig_usleep(20 * 1000);
         }
       else
         {
@@ -2136,8 +2209,8 @@ static int max3421e_ctrl_senddata(FAR struct max3421e_usbhost_s *priv,
  * Name: max3421e_ctrl_recvdata
  *
  * Description:
- *   Receive data in the data phase of an IN control transfer.  Or receive status
- *   in the status phase of an OUT control transfer
+ *   Receive data in the data phase of an IN control transfer.  Or receive
+ *   status in the status phase of an OUT control transfer
  *
  * Assumptions:
  *   The SPI is not locked.  This function is called only from the CTRLIN
@@ -2447,6 +2520,7 @@ static uint8_t max3421e_get_rcvfifo(FAR struct max3421e_usbhost_s *priv,
   priv->xfrd += nrcvd;
 
   /* Discard any byte remaining in the RCVFIFO */
+
   /* REVISIT:  Is this necessary?  Or the MAX3421E automatically discard any
    * unread data?
    */
@@ -2533,10 +2607,10 @@ static void max3421e_recv_continue(FAR struct max3421e_usbhost_s *priv)
    * of the requested data has been received
    */
 
-   if (nrcvd < chan->maxpacket || priv->xfrd >= priv->buflen)
-     {
-       max3421e_transfer_terminate(priv, chan, OK);
-     }
+  if (nrcvd < chan->maxpacket || priv->xfrd >= priv->buflen)
+    {
+      max3421e_transfer_terminate(priv, chan, OK);
+    }
 
   /* If not all of the data has been received, then setup to receive
    * another packet.
@@ -2710,13 +2784,14 @@ static ssize_t max3421e_in_transfer(FAR struct max3421e_usbhost_s *priv,
                     }
                   else
                     {
-                      /* For Isochronous endpoints, bInterval must be 1.  Bulk
-                       * endpoints do not have a polling interval.  Rather,
-                       * the should wait until data is received.
+                      /* For Isochronous endpoints, bInterval must be 1.
+                       * Bulk endpoints do not have a polling interval.
+                       * Rather, the should wait until data is received.
                        *
-                       * REVISIT:  For bulk endpoints this 1 msec delay is only
-                       * intended to give the CPU a break from the bulk EP tight
-                       * polling loop.  But are there performance issues?
+                       * REVISIT:  For bulk endpoints this 1 msec delay is
+                       * only intended to give the CPU a break from the bulk
+                       * EP tight polling loop.  But are there performance
+                       * issues?
                        */
 
                       delay = 1000;
@@ -2725,12 +2800,14 @@ static ssize_t max3421e_in_transfer(FAR struct max3421e_usbhost_s *priv,
                   /* Wait for the next polling interval.  For interrupt and
                    * isochronous endpoints, this is necessary to assure the
                    * polling interval.  It is used in other cases only to
-                   * prevent the polling from consuming too much CPU bandwidth.
+                   * prevent the polling from consuming too much CPU
+                   * bandwidth.
                    *
-                   * Small delays could require more resolution than is provided
-                   * by the system timer.  For example, if the system timer
-                   * resolution is 10MS, then nxsig_usleep(1000) will actually request
-                   * a delay 20MS (due to both quantization and rounding).
+                   * Small delays could require more resolution than is
+                   * provided by the system timer.  For example, if the
+                   * system timer resolution is 10MS, then nxsig_usleep(1000)
+                   * will actually request a delay 20MS (due to both
+                   * quantization and rounding).
                    *
                    * REVISIT: So which is better?  To ignore tiny delays and
                    * hog the system bandwidth?  Or to wait for an excessive
@@ -2871,9 +2948,9 @@ static int max3421e_in_asynch(FAR struct max3421e_usbhost_s *priv,
 
   /* Set up for the transfer based on the direction and the endpoint type */
 
-  max3421_lock(priv);
+  max3421e_lock(priv);
   ret = max3421e_in_setup(priv, chan);
-  max3421_unlock(priv);
+  max3421e_unlock(priv);
 
   if (ret < 0)
     {
@@ -3046,8 +3123,8 @@ static void max3421e_irqwork(FAR void *arg)
 
   max3421e_lock(priv);
 
-  /* Loop while there are pending interrupts to process.  This loop may save a
-   * little interrupt handling overhead.
+  /* Loop while there are pending interrupts to process.  This loop may save
+   * a little interrupt handling overhead.
    */
 
   for (; ; )
@@ -3090,7 +3167,6 @@ static void max3421e_irqwork(FAR void *arg)
 
           max3421e_int_disable(priv, USBHOST_HIRQ_HXFRDNIRQ);
 
-
           /* Clear the pending HXFRDN interrupt */
 
           max3421e_int_clear(priv, USBHOST_HIRQ_HXFRDNIRQ);
@@ -3247,7 +3323,8 @@ static inline void max3421e_int_disable(FAR struct max3421e_usbhost_s *priv,
 
 /* Get the set of pending interrupts */
 
-static inline uint8_t max3421e_int_status(FAR struct max3421e_usbhost_s *priv)
+static inline uint8_t
+  max3421e_int_status(FAR struct max3421e_usbhost_s *priv)
 {
   return max3421e_getreg(priv, MAX3421E_USBHOST_HIRQ) & priv->irqset;
 }
@@ -3287,10 +3364,10 @@ static void max3421e_int_wait(FAR struct max3421e_usbhost_s *priv,
  *   Wait for a device to be connected or disconnected to/from a hub port.
  *
  * Input Parameters:
- *   conn - The USB host connection instance obtained as a parameter from the call to
- *      the USB driver initialization logic.
+ *   conn  - The USB host connection instance obtained as a parameter from
+ *           the call to the USB driver initialization logic.
  *   hport - The location to return the hub port descriptor that detected the
- *      connection related event.
+ *           connection related event.
  *
  * Returned Value:
  *   Zero (OK) is returned on success when a device is connected or
@@ -3311,6 +3388,7 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
   FAR struct max3421e_connection_s *maxconn;
   FAR struct max3421e_usbhost_s *priv;
   struct usbhost_hubport_s *connport;
+  int ret;
 
   maxconn = (FAR struct max3421e_connection_s *)conn;
   DEBUGASSERT(maxconn != NULL && maxconn->priv != NULL);
@@ -3322,7 +3400,11 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
     {
       /* We must have exclusive access to the USB host hardware and state structures */
 
-      max3421e_take_exclsem(priv);
+      ret = max3421e_take_exclsem(priv);
+      if (ret < 0)
+        {
+          return ret;
+        }
 
       /* Is there a change in the connection state of the single root hub
        * port?
@@ -3371,7 +3453,11 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
 
       priv->pscwait = true;
       max3421e_give_exclsem(priv);
-      max3421e_takesem(&priv->pscsem);
+      ret = max3421e_takesem(&priv->pscsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
     }
 }
 
@@ -3389,8 +3475,8 @@ static int max3421e_wait(FAR struct usbhost_connection_s *conn,
  *      device.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   The caller has the SPI bus locked.
@@ -3423,7 +3509,7 @@ static int max3421e_getspeed(FAR struct max3421e_usbhost_s *priv,
    * 100ms.
    */
 
-  nxsig_usleep(100*1000);
+  nxsig_usleep(100 * 1000);
 
   /* Make sure we are still connected */
 
@@ -3472,8 +3558,8 @@ static int max3421e_getspeed(FAR struct max3421e_usbhost_s *priv,
  *      device.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -3493,7 +3579,11 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* If this is a connection on the root hub, then we need to go to
    * little more effort to get the device speed.  If it is a connection
@@ -3511,8 +3601,8 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
       ret = max3421e_getspeed(priv, conn, hport);
       if (ret < 0)
         {
-           max3421e_give_exclsem(priv);
-           return ret;
+          max3421e_give_exclsem(priv);
+          return ret;
         }
     }
 
@@ -3549,14 +3639,14 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
   max3421e_lock(priv);
   max3421e_modifyreg(priv, MAX3421E_USBHOST_HCTL,
                      USBHOST_HCTL_TOGGLES_MASK,
-                     USBHOST_HCTL_RCVTOG0| USBHOST_HCTL_SNDTOG0);
+                     USBHOST_HCTL_RCVTOG0 | USBHOST_HCTL_SNDTOG0);
   max3421e_unlock(priv);
 
   max3421e_give_exclsem(priv);
   return ret;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_ep0configure
  *
  * Description:
@@ -3565,36 +3655,43 @@ static int max3421e_enumerate(FAR struct usbhost_connection_s *conn,
  *   external implementation of the enumeration logic.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   ep0 - The (opaque) EP0 endpoint instance
- *   funcaddr - The USB address of the function containing the endpoint that EP0
- *     controls
- *   speed - The speed of the port USB_SPEED_LOW or _FULL
+ *   drvr          - The USB host driver instance obtained as a parameter
+ *                   from the call to the class create() method.
+ *   ep0           - The (opaque) EP0 endpoint instance
+ *   funcaddr      - The USB address of the function containing the endpoint
+ *                   that EP0 controls
+ *   speed         - The speed of the port USB_SPEED_LOW or _FULL
  *   maxpacketsize - The maximum number of bytes that can be sent to or
- *    received from the endpoint in a single data packet
+ *                   received from the endpoint in a single data packet
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static int max3421e_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
+static int max3421e_ep0configure(FAR struct usbhost_driver_s *drvr,
+                                 usbhost_ep_t ep0,
                                  uint8_t funcaddr, uint8_t speed,
                                  uint16_t maxpacketsize)
 {
-  FAR struct max3421e_usbhost_s *priv = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   FAR struct max3421e_chan_s *chan;
+  int ret;
 
   DEBUGASSERT(drvr != NULL && funcaddr < 128 && maxpacketsize <= 64);
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Configure the EP0 channel */
 
@@ -3608,39 +3705,41 @@ static int max3421e_ep0configure(FAR struct usbhost_driver_s *drvr, usbhost_ep_t
   return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_epalloc
  *
  * Description:
  *   Allocate and configure one endpoint.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
  *   epdesc - Describes the endpoint to be allocated.
- *   ep - A memory location provided by the caller in which to receive the
- *      allocated endpoint descriptor.
+ *   ep     - A memory location provided by the caller in which to receive
+ *            the allocated endpoint descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static int max3421e_epalloc(FAR struct usbhost_driver_s *drvr,
                             FAR const struct usbhost_epdesc_s *epdesc,
                             FAR usbhost_ep_t *ep)
 {
-  FAR struct max3421e_usbhost_s *priv = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   struct usbhost_hubport_s *hport;
   FAR struct max3421e_chan_s *chan;
   int chidx;
+  int ret;
 
-  /* Sanity check.  NOTE that this method should only be called if a device is
-   * connected (because we need a valid low speed indication).
+  /* Sanity check.  NOTE that this method should only be called if a device
+   * is connected (because we need a valid low speed indication).
    */
 
   DEBUGASSERT(drvr != 0 && epdesc != NULL && ep != NULL);
@@ -3649,7 +3748,11 @@ static int max3421e_epalloc(FAR struct usbhost_driver_s *drvr,
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Allocate a host channel for the endpoint */
 
@@ -3661,10 +3764,10 @@ static int max3421e_epalloc(FAR struct usbhost_driver_s *drvr,
       return chidx;
     }
 
-  /* Decode the endpoint descriptor to initialize the channel data structures.
-   * Note:  Here we depend on the fact that the endpoint point type is
-   * encoded in the same way in the endpoint descriptor as it is in the OTG
-   * HS hardware.
+  /* Decode the endpoint descriptor to initialize the channel data
+   * structures.  Note:  Here we depend on the fact that the endpoint point
+   * type is encoded in the same way in the endpoint descriptor as it is in
+   * the OTG HS hardware.
    */
 
   chan            = &priv->chan[chidx];
@@ -3684,68 +3787,76 @@ static int max3421e_epalloc(FAR struct usbhost_driver_s *drvr,
   return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_epfree
  *
  * Description:
  *   Free and endpoint previously allocated by DRVR_EPALLOC.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   ep - The endpoint to be freed.
+ *   drvr - The USB host driver instance obtained as a parameter from the
+ *          call to the class create() method.
+ *   ep   - The endpoint to be freed.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static int max3421e_epfree(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
+static int max3421e_epfree(FAR struct usbhost_driver_s *drvr,
+                           usbhost_ep_t ep)
 {
-  FAR struct max3421e_usbhost_s *priv = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
+  int ret;
 
   DEBUGASSERT(priv);
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret >= 0)
+    {
+      /* Halt the channel and mark the channel available */
 
-  /* Halt the channel and mark the channel available */
+      max3421e_chan_free(priv, (intptr_t)ep);
+      max3421e_give_exclsem(priv);
+    }
 
-  max3421e_chan_free(priv, (intptr_t)ep);
-  max3421e_give_exclsem(priv);
-  return OK;
+  return ret;
 }
 
 /****************************************************************************
  * Name: max3421e_alloc
  *
  * Description:
- *   Some hardware supports special memory in which request and descriptor data can
- *   be accessed more efficiently.  This method provides a mechanism to allocate
- *   the request/descriptor memory.  If the underlying hardware does not support
- *   such "special" memory, this functions may simply map to kmm_malloc.
+ *   Some hardware supports special memory in which request and descriptor
+ *   data can be accessed more efficiently.  This method provides a
+ *   mechanism to allocate the request/descriptor memory.  If the underlying
+ *   hardware does not support such "special" memory, this functions may
+ *   simply map to kmm_malloc.
  *
- *   This interface was optimized under a particular assumption.  It was assumed
- *   that the driver maintains a pool of small, pre-allocated buffers for descriptor
- *   traffic.  NOTE that size is not an input, but an output:  The size of the
- *   pre-allocated buffer is returned.
+ *   This interface was optimized under a particular assumption.  It was
+ *   assumed that the driver maintains a pool of small, pre-allocated
+ *   buffers for descriptor traffic.  NOTE that size is not an input, but
+ *   an output:  The size of the pre-allocated buffer is returned.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   buffer - The address of a memory location provided by the caller in which to
- *     return the allocated buffer memory address.
- *   maxlen - The address of a memory location provided by the caller in which to
- *     return the maximum size of the allocated buffer memory.
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
+ *   buffer - The address of a memory location provided by the caller in
+ *            which to return the allocated buffer memory address.
+ *   maxlen - The address of a memory location provided by the caller in
+ *            which to return the maximum size of the allocated buffer
+ *             memory.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   - Called from a single thread so no mutual exclusion is required.
@@ -3779,26 +3890,28 @@ static int max3421e_alloc(FAR struct usbhost_driver_s *drvr,
  * Name: max3421e_free
  *
  * Description:
- *   Some hardware supports special memory in which request and descriptor data can
- *   be accessed more efficiently.  This method provides a mechanism to free that
- *   request/descriptor memory.  If the underlying hardware does not support
- *   such "special" memory, this functions may simply map to kmm_free().
+ *   Some hardware supports special memory in which request and descriptor
+ *   data can be accessed more efficiently.  This method provides a
+ *   mechanism to free that request/descriptor memory.  If the underlying
+ *   hardware does not support such "special" memory, this functions may
+ *   simply map to kmm_free().
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
  *   buffer - The address of the allocated buffer memory to be freed.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   - Never called from an interrupt handler.
  *
  ****************************************************************************/
 
-static int max3421e_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
+static int max3421e_free(FAR struct usbhost_driver_s *drvr,
+                         FAR uint8_t *buffer)
 {
   /* There is no special memory requirement */
 
@@ -3807,32 +3920,34 @@ static int max3421e_free(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
   return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_ioalloc
  *
  * Description:
  *   Some hardware supports special memory in which larger IO buffers can
- *   be accessed more efficiently.  This method provides a mechanism to allocate
- *   the request/descriptor memory.  If the underlying hardware does not support
- *   such "special" memory, this functions may simply map to kmm_malloc.
+ *   be accessed more efficiently.  This method provides a mechanism to
+ *   allocate the request/descriptor memory.  If the underlying hardware
+ *   does not support such "special" memory, this functions may simply map
+ *   to kmm_malloc.
  *
- *   This interface differs from DRVR_ALLOC in that the buffers are variable-sized.
+ *   This interface differs from DRVR_ALLOC in that the buffers are
+ *   variable-sized.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   buffer - The address of a memory location provided by the caller in which to
- *     return the allocated buffer memory address.
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
+ *   buffer - The address of a memory location provided by the caller in
+ *            which to return the allocated buffer memory address.
  *   buflen - The size of the buffer required.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 static int max3421e_ioalloc(FAR struct usbhost_driver_s *drvr,
                             FAR uint8_t **buffer, size_t buflen)
@@ -3855,30 +3970,31 @@ static int max3421e_ioalloc(FAR struct usbhost_driver_s *drvr,
   return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_iofree
  *
  * Description:
- *   Some hardware supports special memory in which IO data can  be accessed more
- *   efficiently.  This method provides a mechanism to free that IO buffer
- *   memory.  If the underlying hardware does not support such "special" memory,
- *   this functions may simply map to kmm_free().
+ *   Some hardware supports special memory in which IO data can  be accessed
+ *   more efficiently.  This method provides a mechanism to free that IO
+ *   buffer memory.  If the underlying hardware does not support such
+ *   "special" memory, this functions may simply map to kmm_free().
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
  *   buffer - The address of the allocated buffer memory to be freed.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static int max3421e_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffer)
+static int max3421e_iofree(FAR struct usbhost_driver_s *drvr,
+                           FAR uint8_t *buffer)
 {
   /* There is no special memory requirement */
 
@@ -3892,29 +4008,30 @@ static int max3421e_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffe
  *
  * Description:
  *   Process a IN or OUT request on the control endpoint.  These methods
- *   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.
+ *   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.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   ep0 - The control endpoint to send/receive the control request.
- *   req - Describes the request to be sent.  This request must lie in memory
- *      created by DRVR_ALLOC.
+ *   drvr   - The USB host driver instance obtained as a parameter from
+ *            the call to the class create() method.
+ *   ep0    - The control endpoint to send/receive the control request.
+ *   req    - Describes the request to be sent.  This request must lie in
+ *            memory created by DRVR_ALLOC.
  *   buffer - A buffer used for sending the request and for returning any
- *     responses.  This buffer must be large enough to hold the length value
- *     in the request description. buffer must have been allocated using DRVR_ALLOC.
+ *            responses.  This buffer must be large enough to hold the
+ *            length value in the request description. buffer must have been
+ *            allocated using DRVR_ALLOC.
  *
- *   NOTE: On an IN transaction, req and buffer may refer to the same allocated
- *   memory.
+ *   NOTE: On an IN transaction, req and buffer may refer to the same
+ *   allocated memory.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   - Called from a single thread so no mutual exclusion is required.
@@ -3922,7 +4039,8 @@ static int max3421e_iofree(FAR struct usbhost_driver_s *drvr, FAR uint8_t *buffe
  *
  ****************************************************************************/
 
-static int max3421e_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
+static int max3421e_ctrlin(FAR struct usbhost_driver_s *drvr,
+                           usbhost_ep_t ep0,
                            FAR const struct usb_ctrlreq_s *req,
                            FAR uint8_t *buffer)
 {
@@ -3951,7 +4069,11 @@ static int max3421e_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Loop, retrying until the retry time expires */
 
@@ -3972,6 +4094,7 @@ static int max3421e_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
       do
         {
           /* Handle the IN data phase (if any) */
+
           /* The MAX4321E sends fixed DATA0 and DATA1 PID tokens for the
            * various stages of a CONTROL transfer, regardless of the
            * setting of the internal data toggle.
@@ -4015,11 +4138,13 @@ static int max3421e_ctrlin(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
   return -ETIMEDOUT;
 }
 
-static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
+static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr,
+                            usbhost_ep_t ep0,
                             FAR const struct usb_ctrlreq_s *req,
                             FAR const uint8_t *buffer)
 {
-  FAR struct max3421e_usbhost_s *priv = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   FAR struct max3421e_chan_s *chan;
   uint16_t buflen;
   clock_t start;
@@ -4044,7 +4169,11 @@ static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Loop, retrying until the retry time expires */
 
@@ -4065,9 +4194,10 @@ static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
       do
         {
           /* Handle the data OUT phase (if any) */
+
           /* The MAX4321E sends fixed DATA0 and DATA1 PID tokens for the
-           * various stages of a CONTROL transfer, regardless of the
-           * setting of the internal data toggle.
+           * various stages of a CONTROL transfer, regardless of the setting
+           * of the internal data toggle.
            */
 
           if (buflen > 0)
@@ -4115,26 +4245,27 @@ static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
  *
  * Description:
  *   Process a request to handle a transfer descriptor.  This method will
- *   enqueue the transfer request, blocking until the transfer completes. Only
- *   one transfer may be  queued; Neither this method nor the ctrlin or
+ *   enqueue the transfer request, blocking until the transfer completes.
+ *   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
- *      the class create() method.
- *   ep - The IN or OUT endpoint descriptor for the device endpoint on which to
- *      perform the transfer.
- *   buffer - A buffer containing the data to be sent (OUT endpoint) or received
- *     (IN endpoint).  buffer must have been allocated using DRVR_ALLOC
+ *   drvr   - The USB host driver instance obtained as a parameter from the
+ *            call to the class create() method.
+ *   ep     - The IN or OUT endpoint descriptor for the device endpoint on
+ *            which to perform the transfer.
+ *   buffer - A buffer containing the data to be sent (OUT endpoint) or
+ *            received (IN endpoint).  buffer must have been allocated
+ *            using DRVR_ALLOC
  *   buflen - The length of the data to be sent or received.
  *
  * Returned Value:
  *   On success, a non-negative value is returned that indicates the number
- *   of bytes successfully transferred.  On a failure, a negated errno value is
- *   returned that indicates the nature of the failure:
+ *   of bytes successfully transferred.  On a failure, a negated errno value
+ *   is returned that indicates the nature of the failure:
  *
  *     EAGAIN - If devices NAKs the transfer (or NYET or other error where
  *              it may be appropriate to restart the entire transaction).
@@ -4148,12 +4279,15 @@ static int max3421e_ctrlout(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep0,
  *
  ****************************************************************************/
 
-static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
-                                 FAR uint8_t *buffer, size_t buflen)
+static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr,
+                                 usbhost_ep_t ep, FAR uint8_t *buffer,
+                                 size_t buflen)
 {
-  FAR struct max3421e_usbhost_s *priv  = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   FAR struct max3421e_chan_s *chan;
   ssize_t nbytes;
+  int ret;
 
   DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0);
   DEBUGASSERT((intptr_t)ep >= 0 && (intptr_t)ep < MAX3421E_NHOST_CHANNELS);
@@ -4163,7 +4297,11 @@ static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Handle IN and OUT transfer differently */
 
@@ -4194,20 +4332,21 @@ static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t
  *   ctrlout methods can be called again until the transfer completes.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   ep - The IN or OUT endpoint descriptor for the device endpoint on which to
- *      perform the transfer.
- *   buffer - A buffer containing the data to be sent (OUT endpoint) or received
- *     (IN endpoint).  buffer must have been allocated using DRVR_ALLOC
- *   buflen - The length of the data to be sent or received.
+ *   drvr     - The USB host driver instance obtained as a parameter from
+ *              the call to the class create() method.
+ *   ep       - The IN or OUT endpoint descriptor for the device endpoint
+ *              on which to perform the transfer.
+ *   buffer   - A buffer containing the data to be sent (OUT endpoint) or
+ *              received (IN endpoint).  buffer must have been allocated
+ *              using DRVR_ALLOC
+ *   buflen   - The length of the data to be sent or received.
  *   callback - This function will be called when the transfer completes.
- *   arg - The arbitrary parameter that will be passed to the callback function
- *     when the transfer completes.
+ *   arg      - The arbitrary parameter that will be passed to the callback
+ *              function when the transfer completes.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   - Called from a single thread so no mutual exclusion is required.
@@ -4216,11 +4355,13 @@ static ssize_t max3421e_transfer(FAR struct usbhost_driver_s *drvr, usbhost_ep_t
  ****************************************************************************/
 
 #ifdef CONFIG_USBHOST_ASYNCH
-static int max3421e_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
+static int max3421e_asynch(FAR struct usbhost_driver_s *drvr,
+                           usbhost_ep_t ep,
                            FAR uint8_t *buffer, size_t buflen,
                            usbhost_asynch_t callback, FAR void *arg)
 {
-  FAR struct max3421e_usbhost_s *priv  = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   FAR struct max3421e_chan_s *chan;
   int ret;
 
@@ -4232,7 +4373,11 @@ static int max3421e_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
 
   /* We must have exclusive access to the USB host hardware and state structures */
 
-  max3421e_take_exclsem(priv);
+  ret = max3421e_take_exclsem(priv);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Handle IN and OUT transfer slightly differently */
 
@@ -4250,7 +4395,7 @@ static int max3421e_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
 }
 #endif /* CONFIG_USBHOST_ASYNCH */
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_cancel
  *
  * Description:
@@ -4258,20 +4403,22 @@ static int max3421e_asynch(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep,
  *   asynchronous transfer will complete normally with the error -ESHUTDOWN.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   ep - The IN or OUT endpoint descriptor for the device endpoint on which an
- *      asynchronous transfer should be transferred.
+ *   drvr - The USB host driver instance obtained as a parameter from the
+ *          call to the class create() method.
+ *   ep   - The IN or OUT endpoint descriptor for the device endpoint on
+ *          which an asynchronous transfer should be transferred.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure.
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
-static int max3421e_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
+static int max3421e_cancel(FAR struct usbhost_driver_s *drvr,
+                           usbhost_ep_t ep)
 {
-  FAR struct max3421e_usbhost_s *priv  = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   FAR struct max3421e_chan_s *chan;
   irqstate_t flags;
 
@@ -4281,8 +4428,8 @@ static int max3421e_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
 
   usbhost_vtrace1(MAX3421E_VTRACE1_CANCEL, (intptr_t)ep);
 
-  /* We need to disable interrupts to avoid race conditions with the asynchronous
-   * completion of the transfer being canceled.
+  /* We need to disable interrupts to avoid race conditions with the
+   * asynchronous completion of the transfer being canceled.
    */
 
   flags = enter_critical_section();
@@ -4338,7 +4485,7 @@ static int max3421e_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
   return OK;
 }
 
-/************************************************************************************
+/****************************************************************************
  * Name: max3421e_connect
  *
  * Description:
@@ -4347,24 +4494,25 @@ static int max3421e_cancel(FAR struct usbhost_driver_s *drvr, usbhost_ep_t ep)
  *   and port description to the system.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   hport - The descriptor of the hub port that detected the connection
- *      related event
+ *   drvr      - The USB host driver instance obtained as a parameter from
+ *               the call to the class create() method.
+ *   hport     - The descriptor of the hub port that detected the connection
+ *               related event
  *   connected - True: device connected; false: device disconnected
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure.
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure.
  *
- ************************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_USBHOST_HUB
 static int max3421e_connect(FAR struct usbhost_driver_s *drvr,
                             FAR struct usbhost_hubport_s *hport,
                             bool connected)
 {
-  FAR struct max3421e_usbhost_s *priv = (FAR struct max3421e_usbhost_s *)drvr;
+  FAR struct max3421e_usbhost_s *priv =
+    (FAR struct max3421e_usbhost_s *)drvr;
   irqstate_t flags;
 
   DEBUGASSERT(priv != NULL && hport != NULL);
@@ -4393,17 +4541,18 @@ static int max3421e_connect(FAR struct usbhost_driver_s *drvr,
  * Name: max3421e_disconnect
  *
  * Description:
- *   Called by the class when an error occurs and driver has been disconnected.
- *   The USB host driver should discard the handle to the class instance (it is
- *   stale) and not attempt any further interaction with the class driver instance
- *   (until a new instance is received from the create() method).  The driver
- *   should not called the class' disconnected() method.
+ *   Called by the class when an error occurs and driver has been
+ *   disconnected.  The USB host driver should discard the handle to the
+ *   class instance (it is stale) and not attempt any further interaction
+ *   with the class driver instance (until a new instance is received from
+ *   the create() method).  The driver should not called the class'
+ *   disconnected() method.
  *
  * Input Parameters:
- *   drvr - The USB host driver instance obtained as a parameter from the call to
- *      the class create() method.
- *   hport - The port from which the device is being disconnected.  Might be a port
- *      on a hub.
+ *   drvr  - The USB host driver instance obtained as a parameter from the
+ *           call to the class create() method.
+ *   hport - The port from which the device is being disconnected.  Might be
+ *           a port on a hub.
  *
  * Returned Value:
  *   None
@@ -4505,6 +4654,7 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
     {
       default:
       case (USBHOST_HRSL_KSTATUS | USBHOST_HRSL_JSTATUS):
+
         /* Invalid state */
 
         usbhost_trace1(MAX3421E_TRACE1_BAD_JKSTATE, regval);
@@ -4512,11 +4662,13 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
         /* Fall through */
 
       case 0:
+
         /* 0:  Not connected */
 
         return -ENODEV;
 
       case USBHOST_HRSL_KSTATUS:
+
         /* J=0, K=1: low-speed in full-speed (or vice versa) */
 
         if (lowspeed)
@@ -4534,6 +4686,7 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
         break;
 
       case USBHOST_HRSL_JSTATUS:
+
         /* J=1,K=0: full-speed in full-speed (or vice versa) */
 
         if (lowspeed)
@@ -4548,6 +4701,7 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
 
             clrbits |= USBHOST_MODE_SPEED;
           }
+
         break;
     }
 
@@ -4555,10 +4709,10 @@ static int max3421e_startsof(FAR struct max3421e_usbhost_s *priv)
 
   max3421e_modifyreg(priv, MAX3421E_USBHOST_MODE, clrbits, setbits);
 
- /* Wait for the first SOF received and 20ms has passed */
+  /* Wait for the first SOF received and 20ms has passed */
 
   max3421e_int_wait(priv, USBHOST_HIRQ_FRAMEIRQ, 0);
-  nxsig_usleep(20*1000);
+  nxsig_usleep(20 * 1000);
   return OK;
 }
 
@@ -4868,18 +5022,18 @@ errout_with_alloc:
   return NULL;
 }
 
-/********************************************************************************************
+/****************************************************************************
  * Name: usbhost_trformat1 and usbhost_trformat2
  *
  * Description:
  *   This interface must be provided by platform specific logic that knows
  *   the HCDs encoding of USB trace data.
  *
- *   Given an 9-bit index, return a format string suitable for use with, say,
- *   printf.  The returned format is expected to handle two unsigned integer
- *   values.
+ *   Given an 9-bit index, return a format string suitable for use with,
+ *   say, printf.  The returned format is expected to handle two unsigned
+ *   integer values.
  *
- ********************************************************************************************/
+ ****************************************************************************/
 
 #ifdef HAVE_USBHOST_TRACE
 FAR const char *usbhost_trformat1(uint16_t id)
diff --git a/drivers/usbhost/usbhost_skeleton.c b/drivers/usbhost/usbhost_skeleton.c
index 01e1636..025a429 100644
--- a/drivers/usbhost/usbhost_skeleton.c
+++ b/drivers/usbhost/usbhost_skeleton.c
@@ -1,35 +1,20 @@
 /****************************************************************************
  * drivers/usbhost/usbhost_skeleton.c
  *
- *   Copyright (C) 2018 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <gnutt@nuttx.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- *    used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
  *
  ****************************************************************************/
 
@@ -67,6 +52,7 @@
 #endif
 
 /* Driver support ***********************************************************/
+
 /* 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.
  */
@@ -117,7 +103,8 @@ struct usbhost_state_s
 
 /* Semaphores */
 
-static void usbhost_takesem(sem_t *sem);
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Memory allocation services */
@@ -157,8 +144,9 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv);
 
 /* struct usbhost_registry_s methods */
 
-static struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
-                                              FAR const struct usbhost_id_s *id);
+static struct usbhost_class_s *
+  usbhost_create(FAR struct usbhost_hubport_s *hport,
+                 FAR const struct usbhost_id_s *id);
 
 /* struct usbhost_class_s methods */
 
@@ -212,9 +200,37 @@ static uint32_t g_devinuse;
  *
  ****************************************************************************/
 
-static void usbhost_takesem(sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -241,7 +257,10 @@ static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
   FAR struct usbhost_state_s *priv;
 
   DEBUGASSERT(!up_interrupt_context());
-  priv = (FAR struct usbhost_state_s *)kmm_malloc(sizeof(struct usbhost_state_s));
+
+  priv = (FAR struct usbhost_state_s *)
+    kmm_malloc(sizeof(struct usbhost_state_s));
+
   uinfo("Allocated: %p\n", priv);
   return priv;
 }
@@ -396,8 +415,8 @@ static void usbhost_destroy(FAR void *arg)
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -454,7 +473,8 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_INTERFACE:
           {
-            FAR struct usb_ifdesc_s *ifdesc = (FAR struct usb_ifdesc_s *)configdesc;
+            FAR struct usb_ifdesc_s *ifdesc =
+              (FAR struct usb_ifdesc_s *)configdesc;
 
             uinfo("Interface descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_IFDESC);
@@ -472,14 +492,16 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_ENDPOINT:
           {
-            FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
 
             uinfo("Endpoint descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
 
             /* Check for a bulk endpoint. */
 
-            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_BULK)
+            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_BULK)
               {
                 /* Yes.. it is a bulk endpoint.  IN or OUT? */
 
@@ -497,16 +519,20 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
                         return -EINVAL;
                       }
+
                     found |= USBHOST_BOUTFOUND;
 
                     /* Save the bulk OUT endpoint information */
 
                     boutdesc.hport        = hport;
-                    boutdesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    boutdesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
                     boutdesc.in           = false;
                     boutdesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
                     boutdesc.interval     = epdesc->interval;
-                    boutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    boutdesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uinfo("Bulk OUT EP addr:%d mxpacketsize:%d\n",
                           boutdesc.addr, boutdesc.mxpacketsize);
                   }
@@ -530,11 +556,14 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the bulk IN endpoint information */
 
                     bindesc.hport        = hport;
-                    bindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    bindesc.addr         = epdesc->addr &
+                                           USB_EP_ADDR_NUMBER_MASK;
                     bindesc.in           = 1;
                     bindesc.xfrtype      = USB_EP_ATTR_XFER_BULK;
                     bindesc.interval     = epdesc->interval;
-                    bindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    bindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uinfo("Bulk IN EP addr:%d mxpacketsize:%d\n",
                           bindesc.addr, bindesc.mxpacketsize);
                   }
@@ -637,7 +666,9 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 
       uinfo("Register block driver\n");
       usbhost_mkdevname(priv, devname);
-      // ret = register_blockdriver(devname, &g_bops, 0, priv);
+#if 0 /* Finish me */
+      ret = register_blockdriver(devname, &g_bops, 0, priv);
+#endif
     }
 
   /* Check if we successfully initialized. We now have to be concerned
@@ -647,7 +678,12 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 
   if (ret >= 0)
     {
-      usbhost_takesem(&priv->exclsem);
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ert;
+        }
+
       DEBUGASSERT(priv->crefs >= 2);
 
       /* Handle a corner case where (1) open() has been called so the
@@ -736,7 +772,8 @@ static inline uint32_t usbhost_getle32(const uint8_t *val)
 {
   /* Little endian means LS halfword first in byte stream */
 
-  return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
+  return (uint32_t)usbhost_getle16(&val[2]) << 16 |
+         (uint32_t)usbhost_getle16(val);
 }
 
 /****************************************************************************
@@ -759,7 +796,7 @@ static void usbhost_putle32(uint8_t *dest, uint32_t val)
   /* Little endian means LS halfword first in byte stream */
 
   usbhost_putle16(dest, (uint16_t)(val & 0xffff));
-  usbhost_putle16(dest+2, (uint16_t)(val >> 16));
+  usbhost_putle16(dest + 2, (uint16_t)(val >> 16));
 }
 
 /****************************************************************************
@@ -829,12 +866,13 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
  * Name: usbhost_create
  *
  * Description:
- *   This function implements the create() method of struct usbhost_registry_s.
- *   The create() method is a callback into the class implementation.  It is
- *   used to (1) create a new instance of the USB host class state and to (2)
- *   bind a USB host driver "session" to the class instance.  Use of this
- *   create() method will support environments where there may be multiple
- *   USB ports and multiple USB devices simultaneously connected.
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
  *
  * Input Parameters:
  *   hport - The hub hat manages the new class instance.
@@ -850,8 +888,9 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
  *
  ****************************************************************************/
 
-static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
-                                                  FAR const struct usbhost_id_s *id)
+static FAR struct usbhost_class_s *
+  usbhost_create(FAR struct usbhost_hubport_s *hport,
+                 FAR const struct usbhost_id_s *id)
 {
   FAR struct usbhost_state_s *priv;
 
@@ -868,7 +907,7 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *
 
       if (usbhost_allocdevno(priv) == OK)
         {
-         /* Initialize class method function pointers */
+          /* Initialize class method function pointers */
 
           priv->usbclass.hport        = hport;
           priv->usbclass.connect      = usbhost_connect;
@@ -894,12 +933,14 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *
     {
       usbhost_freeclass(priv);
     }
+
   return NULL;
 }
 
 /****************************************************************************
  * struct usbhost_class_s methods
  ****************************************************************************/
+
 /****************************************************************************
  * Name: usbhost_connect
  *
@@ -917,11 +958,11 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
- *   NOTE that the class instance remains valid upon return with a failure.  It is
- *   the responsibility of the higher level enumeration logic to call
+ *   NOTE that the class instance remains valid upon return with a failure.
+ *   It is the responsibility of the higher level enumeration logic to call
  *   CLASS_DISCONNECTED to free up the class driver resources.
  *
  * Assumptions:
@@ -1016,10 +1057,12 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
         {
           /* Destroy the instance on the worker thread. */
 
-          uinfo("Queuing destruction: worker %p->%p\n", priv->work.worker, usbhost_destroy);
+          uinfo("Queuing destruction: worker %p->%p\n",
+                priv->work.worker, usbhost_destroy);
+
           DEBUGASSERT(priv->work.worker == NULL);
           work_queue(HPWORK, &priv->work, usbhost_destroy, priv, 0);
-       }
+        }
       else
         {
           /* Do the work now */
diff --git a/drivers/usbhost/usbhost_storage.c b/drivers/usbhost/usbhost_storage.c
index db78ddc..2d23e34 100644
--- a/drivers/usbhost/usbhost_storage.c
+++ b/drivers/usbhost/usbhost_storage.c
@@ -138,7 +138,8 @@ struct usbhost_freestate_s
 
 /* Semaphores */
 
-static void usbhost_takesem(sem_t *sem);
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Memory allocation services */
@@ -311,9 +312,37 @@ static uint32_t g_devinuse;
  *
  ****************************************************************************/
 
-static void usbhost_takesem(sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -1347,7 +1376,7 @@ static inline int usbhost_initvolume(FAR struct usbhost_state_s *priv)
    * driver has been registered.
    */
 
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
   DEBUGASSERT(priv->crefs >= 2);
 
   /* Decrement the reference count */
@@ -1877,7 +1906,11 @@ static int usbhost_open(FAR struct inode *inode)
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the mass storage device is still connected.  We need to
    * disable interrupts momentarily to assure that there are no asynchronous
@@ -1927,7 +1960,8 @@ static int usbhost_close(FAR struct inode *inode)
   /* Decrement the reference count on the block driver */
 
   DEBUGASSERT(priv->crefs > 1);
-  usbhost_takesem(&priv->exclsem);
+
+  usbhost_forcetake(&priv->exclsem);
   priv->crefs--;
 
   /* Release the semaphore.  The following operations when crefs == 1 are
@@ -1976,6 +2010,7 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
   FAR struct usbhost_state_s *priv;
   FAR struct usbhost_hubport_s *hport;
   ssize_t nbytes = 0;
+  int ret;
 
   DEBUGASSERT(inode && inode->i_private);
   priv = (FAR struct usbhost_state_s *)inode->i_private;
@@ -2001,7 +2036,11 @@ static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
     {
       FAR struct usbmsc_cbw_s *cbw;
 
-      usbhost_takesem(&priv->exclsem);
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
 
       /* Assume allocation failure */
 
@@ -2084,6 +2123,7 @@ static ssize_t usbhost_write(FAR struct inode *inode,
   FAR struct usbhost_state_s *priv;
   FAR struct usbhost_hubport_s *hport;
   ssize_t nbytes;
+  int ret;
 
   uinfo("sector: %d nsectors: %d sectorsize: %d\n");
 
@@ -2108,7 +2148,11 @@ static ssize_t usbhost_write(FAR struct inode *inode,
     {
       FAR struct usbmsc_cbw_s *cbw;
 
-      usbhost_takesem(&priv->exclsem);
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret < 0)
+        {
+          return ret;
+        }
 
       /* Assume allocation failure */
 
@@ -2198,19 +2242,19 @@ static int usbhost_geometry(FAR struct inode *inode,
     {
       /* Return the geometry of the USB mass storage device */
 
-      usbhost_takesem(&priv->exclsem);
-
-      geometry->geo_available     = true;
-      geometry->geo_mediachanged  = false;
-      geometry->geo_writeenabled  = true;
-      geometry->geo_nsectors      = priv->nblocks;
-      geometry->geo_sectorsize    = priv->blocksize;
-      usbhost_givesem(&priv->exclsem);
-
-      uinfo("nsectors: %ld sectorsize: %d\n",
-             (long)geometry->geo_nsectors, geometry->geo_sectorsize);
-
-      ret = OK;
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret >= 0)
+        {
+          geometry->geo_available     = true;
+          geometry->geo_mediachanged  = false;
+          geometry->geo_writeenabled  = true;
+          geometry->geo_nsectors      = priv->nblocks;
+          geometry->geo_sectorsize    = priv->blocksize;
+          usbhost_givesem(&priv->exclsem);
+
+          uinfo("nsectors: %ld sectorsize: %d\n",
+                 (long)geometry->geo_nsectors, geometry->geo_sectorsize);
+        }
     }
 
   return ret;
@@ -2247,17 +2291,20 @@ static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
     {
       /* Process the IOCTL by command */
 
-      usbhost_takesem(&priv->exclsem);
-      switch (cmd)
+      ret = usbhost_takesem(&priv->exclsem);
+      if (ret >= 0)
         {
-        /* Add support for ioctl commands here */
+          switch (cmd)
+            {
+              /* Add support for ioctl commands here */
 
-        default:
-          ret = -ENOTTY;
-          break;
-        }
+              default:
+                ret = -ENOTTY;
+                break;
+            }
 
-      usbhost_givesem(&priv->exclsem);
+          usbhost_givesem(&priv->exclsem);
+        }
     }
 
   return ret;
diff --git a/drivers/usbhost/usbhost_xboxcontroller.c b/drivers/usbhost/usbhost_xboxcontroller.c
index d41b1fa..7f7b082 100644
--- a/drivers/usbhost/usbhost_xboxcontroller.c
+++ b/drivers/usbhost/usbhost_xboxcontroller.c
@@ -201,7 +201,8 @@ struct usbhost_state_s
 
 /* Semaphores */
 
-static void usbhost_takesem(sem_t *sem);
+static int usbhost_takesem(FAR sem_t *sem);
+static void usbhost_forcetake(FAR sem_t *sem);
 #define usbhost_givesem(s) nxsem_post(s);
 
 /* Memory allocation services */
@@ -248,8 +249,9 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv);
 
 /* struct usbhost_registry_s methods */
 
-static struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
-                                              FAR const struct usbhost_id_s *id);
+static struct usbhost_class_s *
+  usbhost_create(FAR struct usbhost_hubport_s *hport,
+                 FAR const struct usbhost_id_s *id);
 
 /* struct usbhost_class_s methods */
 
@@ -283,20 +285,20 @@ static const struct usbhost_id_s g_xboxcontroller_id[] =
 
   {
     USB_CLASS_VENDOR_SPEC,  /* base -- Must be one of the USB_CLASS_* definitions in usb.h */
-    0x0047,  /* subclass -- depends on the device */
-    0x00d0,  /* proto -- depends on the device    */
-    0x045e,  /* vid      */
-    0x02dd   /* pid      */
+    0x0047,                 /* subclass -- depends on the device */
+    0x00d0,                 /* proto -- depends on the device */
+    0x045e,                 /* vid */
+    0x02dd                  /* pid */
   },
 
   /* XBox One S controller */
 
   {
     USB_CLASS_VENDOR_SPEC,  /* base -- Must be one of the USB_CLASS_* definitions in usb.h */
-    0x0047,  /* subclass -- depends on the device */
-    0x00d0,  /* proto -- depends on the device    */
-    0x045e,  /* vid      */
-    0x02ea   /* pid      */
+    0x0047,                 /* subclass -- depends on the device */
+    0x00d0,                 /* proto -- depends on the device */
+    0x045e,                 /* vid */
+    0x02ea                  /* pid */
   }
 };
 
@@ -304,23 +306,23 @@ static const struct usbhost_id_s g_xboxcontroller_id[] =
 
 static struct usbhost_registry_s g_xboxcontroller =
 {
-  NULL,                   /* flink    */
-  usbhost_create,         /* create   */
-  2,                      /* nids     */
-  g_xboxcontroller_id     /* id[]     */
+  NULL,                     /* flink */
+  usbhost_create,           /* create */
+  2,                        /* nids */
+  g_xboxcontroller_id       /* id[] */
 };
 
 /* The configuration information for the block file device. */
 
 static const struct file_operations g_xboxcontroller_fops =
 {
-  usbhost_open,            /* open      */
-  usbhost_close,           /* close     */
-  usbhost_read,            /* read      */
-  usbhost_write,           /* write     */
-  NULL,                    /* seek      */
-  usbhost_ioctl,           /* ioctl     */
-  usbhost_poll             /* poll      */
+  usbhost_open,             /* open */
+  usbhost_close,            /* close */
+  usbhost_read,             /* read */
+  usbhost_write,            /* write */
+  NULL,                     /* seek */
+  usbhost_ioctl,            /* ioctl */
+  usbhost_poll              /* poll */
 };
 
 /* This is a bitmap that is used to allocate device names /dev/xboxa-z. */
@@ -346,9 +348,37 @@ static struct usbhost_state_s *g_priv;    /* Data passed to thread */
  *
  ****************************************************************************/
 
-static void usbhost_takesem(sem_t *sem)
+static int usbhost_takesem(FAR sem_t *sem)
 {
-  nxsem_wait_uninterruptible(sem);
+  return nxsem_wait_uninterruptible(sem);
+}
+
+/****************************************************************************
+ * Name: usbhost_forcetake
+ *
+ * Description:
+ *   This is just another wrapper but this one continues even if the thread
+ *   is canceled.  This must be done in certain conditions where were must
+ *   continue in order to clean-up resources.
+ *
+ ****************************************************************************/
+
+static void usbhost_forcetake(FAR sem_t *sem)
+{
+  int ret;
+
+  do
+    {
+      ret = nxsem_wait_uninterruptible(sem);
+
+      /* The only expected error would -ECANCELED meaning that the
+       * parent thread has been canceled.  We have to continue and
+       * terminate the poll in this case.
+       */
+
+      DEBUGASSERT(ret == OK || ret == -ECANCELED);
+    }
+  while (ret < 0);
 }
 
 /****************************************************************************
@@ -375,7 +405,10 @@ static inline FAR struct usbhost_state_s *usbhost_allocclass(void)
   FAR struct usbhost_state_s *priv;
 
   DEBUGASSERT(!up_interrupt_context());
-  priv = (FAR struct usbhost_state_s *)kmm_malloc(sizeof(struct usbhost_state_s));
+
+  priv = (FAR struct usbhost_state_s *)
+    kmm_malloc(sizeof(struct usbhost_state_s));
+
   uinfo("Allocated: %p\n", priv);
   return priv;
 }
@@ -552,10 +585,10 @@ static void usbhost_pollnotify(FAR struct usbhost_state_s *priv)
       nxsem_post(&priv->waitsem);
     }
 
-  /* If there are threads waiting on poll() for controller data to become available,
-   * then wake them up now.  NOTE: we wake up all waiting threads because we
-   * do not know that they are going to do.  If they all try to read the data,
-   * then some make end up blocking after all.
+  /* If there are threads waiting on poll() for controller data to become
+   * available, then wake them up now.  NOTE: we wake up all waiting threads
+   * because we do not know that they are going to do.  If they all try to
+   * read the data, then some make end up blocking after all.
    */
 
   for (i = 0; i < CONFIG_XBOXCONTROLLER_NPOLLWAITERS; i++)
@@ -600,10 +633,10 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
    * 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 *not* incremented here.  When the driver
-   * structure was created, it was created with a reference count of one.  This
-   * thread is responsible for that count.  The count will be decrement when
-   * this thread exits.
+   * NOTE: that the reference count is *not* incremented here.  When the
+   * driver structure was created, it was created with a reference count of
+   * one.  This thread is responsible for that count.  The count will be
+   * decrement when this thread exits.
    */
 
   priv = g_priv;
@@ -674,7 +707,11 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
                 {
                   /* Get exclusive access to the controller state data */
 
-                  usbhost_takesem(&priv->exclsem);
+                  ret = usbhost_takesem(&priv->exclsem);
+                  if (ret < 0)
+                    {
+                      goto exitloop;
+                    }
 
                   priv->tbuffer[0] = 0x05;
                   priv->tbuffer[1] = 0x20;
@@ -696,15 +733,20 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
 
               /* Get exclusive access to the controller state data */
 
-              usbhost_takesem(&priv->exclsem);
+              ret = usbhost_takesem(&priv->exclsem);
+              if (ret < 0)
+                {
+                  goto exitloop;
+                }
 
               /* Read the data out of the controller report. */
 
-              priv->rpt.guide = (priv->tbuffer[XBOX_BUTTON_GUIDE_INDEX] != 0) ? true : false;
+              priv->rpt.guide =
+                (priv->tbuffer[XBOX_BUTTON_GUIDE_INDEX] != 0) ? true : false;
               priv->valid = true;
 
-              /* The One X controller requires an ACK of the guide button status
-               * message.
+              /* The One X controller requires an ACK of the guide button
+               * status message.
                */
 
               if (priv->tbuffer[1] == 0x30)
@@ -730,8 +772,9 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
 
                   /* Perform the transfer. */
 
-                  nbytes = DRVR_TRANSFER(hport->drvr, priv->epout, priv->tbuffer,
-                                         sizeof(guide_button_report_ack));
+                  nbytes =
+                    DRVR_TRANSFER(hport->drvr, priv->epout, priv->tbuffer,
+                                  sizeof(guide_button_report_ack));
                 }
 
               /* Notify any waiters that new controller data is available */
@@ -752,54 +795,75 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
                 {
                   /* Get exclusive access to the controller state data */
 
-                  usbhost_takesem(&priv->exclsem);
+                  ret = usbhost_takesem(&priv->exclsem);
+                  if (ret < 0)
+                    {
+                      goto exitloop;
+                    }
 
                   /* Read the data out of the controller report. */
 
                   priv->rpt.sync =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_SYNC_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_SYNC_INDEX,
                                     XBOX_BUTTON_SYNC_MASK);
                   priv->rpt.start =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_START_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_START_INDEX,
                                     XBOX_BUTTON_START_MASK);
                   priv->rpt.back =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BACK_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_BACK_INDEX,
                                     XBOX_BUTTON_BACK_MASK);
                   priv->rpt.a =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_A_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_A_INDEX,
                                     XBOX_BUTTON_A_MASK);
                   priv->rpt.b =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_B_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_B_INDEX,
                                     XBOX_BUTTON_B_MASK);
                   priv->rpt.x =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_X_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_X_INDEX,
                                     XBOX_BUTTON_X_MASK);
                   priv->rpt.y =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_Y_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_Y_INDEX,
                                     XBOX_BUTTON_Y_MASK);
                   priv->rpt.dpad_up =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_UP_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_DPAD_UP_INDEX,
                                     XBOX_BUTTON_DPAD_UP_MASK);
                   priv->rpt.dpad_down =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_DOWN_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_DPAD_DOWN_INDEX,
                                     XBOX_BUTTON_DPAD_DOWN_MASK);
                   priv->rpt.dpad_left =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_LEFT_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_DPAD_LEFT_INDEX,
                                     XBOX_BUTTON_DPAD_LEFT_MASK);
                   priv->rpt.dpad_right =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_DPAD_RIGHT_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_DPAD_RIGHT_INDEX,
                                     XBOX_BUTTON_DPAD_RIGHT_MASK);
                   priv->rpt.bumper_left =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BUMPER_LEFT_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_BUMPER_LEFT_INDEX,
                                     XBOX_BUTTON_BUMPER_LEFT_MASK);
                   priv->rpt.bumper_right =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_BUMPER_RIGHT_INDEX, XBOX_BUTTON_BUMPER_RIGHT_MASK);
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_BUMPER_RIGHT_INDEX,
+                                    XBOX_BUTTON_BUMPER_RIGHT_MASK);
                   priv->rpt.stick_click_left =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_STICK_LEFT_INDEX,
-                                   XBOX_BUTTON_STICK_LEFT_MASK);
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_STICK_LEFT_INDEX,
+                                    XBOX_BUTTON_STICK_LEFT_MASK);
                   priv->rpt.stick_click_right =
-                    XBOX_BUTTON_SET(priv->tbuffer, XBOX_BUTTON_STICK_RIGHT_INDEX,
+                    XBOX_BUTTON_SET(priv->tbuffer,
+                                    XBOX_BUTTON_STICK_RIGHT_INDEX,
                                     XBOX_BUTTON_STICK_RIGHT_MASK);
+
                   priv->rpt.trigger_left =
                     ((int16_t *)(priv->tbuffer))[XBOX_BUTTON_TRIGGER_LEFT];
                   priv->rpt.trigger_right =
@@ -844,15 +908,17 @@ static int usbhost_xboxcontroller_poll(int argc, char *argv[])
 #endif
     }
 
-  /* We get here when the driver is removed.. or when too many errors have
-   * been encountered.
+exitloop:
+
+  /* We get here when the driver is removed, when too many errors have
+   * been encountered, or when the thread is canceled.
    *
    * 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);
+  usbhost_forcetake(&priv->exclsem);
 
   /* Indicate that we are no longer running and decrement the reference
    * count held by this thread.  If there are no other users of the class,
@@ -932,7 +998,8 @@ static int usbhost_sample(FAR struct usbhost_state_s *priv,
     {
       /* Return a copy of the sampled data. */
 
-      memcpy(sample, &priv->rpt, sizeof(struct xbox_controller_buttonstate_s));
+      memcpy(sample, &priv->rpt,
+             sizeof(struct xbox_controller_buttonstate_s));
 
       /* The sample has been reported and is no longer valid */
 
@@ -1011,8 +1078,8 @@ static int usbhost_waitsample(FAR struct usbhost_state_s *priv,
   iinfo("Sampled\n");
 
   /* Re-acquire the semaphore that manages mutually exclusive access to
-   * the device structure.  We may have to wait here.  But we have our sample.
-   * Interrupts and pre-emption will be re-enabled while we wait.
+   * the device structure.  We may have to wait here.  But we have our
+   * sample.  Interrupts and pre-emption will be re-enabled while we wait.
    */
 
   ret = nxsem_wait(&priv->exclsem);
@@ -1051,8 +1118,8 @@ errout:
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
  * Assumptions:
  *   This function will *not* be called from an interrupt handler.
@@ -1143,21 +1210,23 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
 
         case USB_DESC_TYPE_ENDPOINT:
           {
-            FAR struct usb_epdesc_s *epdesc = (FAR struct usb_epdesc_s *)configdesc;
+            FAR struct usb_epdesc_s *epdesc =
+              (FAR struct usb_epdesc_s *)configdesc;
 
             uinfo("Endpoint descriptor\n");
             DEBUGASSERT(remaining >= USB_SIZEOF_EPDESC);
 
             /* Check for a interrupt endpoint. */
 
-            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) == USB_EP_ATTR_XFER_INT)
+            if ((epdesc->attr & USB_EP_ATTR_XFERTYPE_MASK) ==
+                USB_EP_ATTR_XFER_INT)
               {
                 /* Yes.. it is a interrupt endpoint.  IN or OUT? */
 
                 if (USB_ISEPOUT(epdesc->addr))
                   {
-                    /* It is an OUT interrupt endpoint.  There should be only one
-                     * interrupt OUT endpoint.
+                    /* It is an OUT interrupt endpoint.  There should be only
+                     * one interrupt OUT endpoint.
                      */
 
                     if ((found & USBHOST_EPOUTFOUND) != 0)
@@ -1174,18 +1243,21 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the bulk OUT endpoint information */
 
                     epoutdesc.hport        = hport;
-                    epoutdesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    epoutdesc.addr         = epdesc->addr &
+                                             USB_EP_ADDR_NUMBER_MASK;
                     epoutdesc.in           = false;
                     epoutdesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     epoutdesc.interval     = epdesc->interval;
-                    epoutdesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    epoutdesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uerr("Interrupt OUT EP addr:%d mxpacketsize:%d\n",
                           epoutdesc.addr, epoutdesc.mxpacketsize);
                   }
                 else
                   {
-                    /* It is an IN interrupt endpoint.  There should be only one
-                     * interrupt IN endpoint.
+                    /* It is an IN interrupt endpoint.  There should be only
+                     * one interrupt IN endpoint.
                      */
 
                     if ((found & USBHOST_EPINFOUND) != 0)
@@ -1202,11 +1274,14 @@ static inline int usbhost_cfgdesc(FAR struct usbhost_state_s *priv,
                     /* Save the bulk IN endpoint information */
 
                     epindesc.hport        = hport;
-                    epindesc.addr         = epdesc->addr & USB_EP_ADDR_NUMBER_MASK;
+                    epindesc.addr         = epdesc->addr &
+                                            USB_EP_ADDR_NUMBER_MASK;
                     epindesc.in           = true;
                     epindesc.xfrtype      = USB_EP_ATTR_XFER_INT;
                     epindesc.interval     = epdesc->interval;
-                    epindesc.mxpacketsize = usbhost_getle16(epdesc->mxpacketsize);
+                    epindesc.mxpacketsize =
+                      usbhost_getle16(epdesc->mxpacketsize);
+
                     uerr("Interrupt IN EP addr:%d mxpacketsize:%d\n",
                           epindesc.addr, epindesc.mxpacketsize);
                   }
@@ -1307,23 +1382,30 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
   priv->crefs++;
   DEBUGASSERT(priv->crefs == 2);
 
-  /* 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_XBOXCONTROLLER_STACKSIZE).
+  /* Start a worker task to poll the USB device.  It would be nice to use
+   * 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_XBOXCONTROLLER_STACKSIZE).
    */
 
-  /* The inputs to a task started by kthread_create() are very awkward for this
-   * purpose.  They are really designed for command line tasks (argc/argv). So
-   * the following is kludge pass binary data when the controller poll task
-   * is started.
+  /* The inputs to a task started by kthread_create() are very awkward for
+   * this purpose.  They are really designed for command line tasks
+   * (argc/argv). So the following is kludge pass binary data when the
+   * controller 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).
+   * 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);
+  ret = usbhost_takesem(&g_exclsem);
+  if (ret < 0)
+    {
+      usbhost_tfree(priv);
+      goto errout;
+    }
+
   g_priv = priv;
 
   uinfo("Starting thread\n");
@@ -1342,7 +1424,7 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
 
   /* Now wait for the poll task to get properly initialized */
 
-  usbhost_takesem(&g_syncsem);
+  usbhost_forcetake(&g_syncsem);
   usbhost_givesem(&g_exclsem);
 
   /* Configure the device */
@@ -1359,7 +1441,7 @@ static inline int usbhost_devinit(FAR struct usbhost_state_s *priv)
    */
 
 errout:
-  usbhost_takesem(&priv->exclsem);
+  usbhost_forcetake(&priv->exclsem);
   priv->crefs--;
   usbhost_givesem(&priv->exclsem);
   return ret;
@@ -1424,7 +1506,8 @@ static inline uint32_t usbhost_getle32(const uint8_t *val)
 {
   /* Little endian means LS halfword first in byte stream */
 
-  return (uint32_t)usbhost_getle16(&val[2]) << 16 | (uint32_t)usbhost_getle16(val);
+  return (uint32_t)usbhost_getle16(&val[2]) << 16 |
+         (uint32_t)usbhost_getle16(val);
 }
 
 /****************************************************************************
@@ -1519,17 +1602,18 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
  * Name: usbhost_create
  *
  * Description:
- *   This function implements the create() method of struct usbhost_registry_s.
- *   The create() method is a callback into the class implementation.  It is
- *   used to (1) create a new instance of the USB host class state and to (2)
- *   bind a USB host driver "session" to the class instance.  Use of this
- *   create() method will support environments where there may be multiple
- *   USB ports and multiple USB devices simultaneously connected.
+ *   This function implements the create() method of struct
+ *   usbhost_registry_s.  The create() method is a callback into the class
+ *   implementation.  It is used to (1) create a new instance of the USB
+ *   host class state and to (2) bind a USB host driver "session" to the
+ *   class instance.  Use of this create() method will support environments
+ *   where there may be multiple USB ports and multiple USB devices
+ *   simultaneously connected.
  *
  * Input Parameters:
  *   hport - The hub hat manages the new class instance.
- *   id - In the case where the device supports multiple base classes,
- *     subclasses, or protocols, this specifies which to configure for.
+ *   id    - In the case where the device supports multiple base classes,
+ *           subclasses, or protocols, this specifies which to configure for.
  *
  * Returned Value:
  *   On success, this function will return a non-NULL instance of struct
@@ -1540,8 +1624,9 @@ static inline int usbhost_tfree(FAR struct usbhost_state_s *priv)
  *
  ****************************************************************************/
 
-static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *hport,
-                                                  FAR const struct usbhost_id_s *id)
+static FAR struct usbhost_class_s *
+  usbhost_create(FAR struct usbhost_hubport_s *hport,
+                 FAR const struct usbhost_id_s *id)
 {
   FAR struct usbhost_state_s *priv;
 
@@ -1616,11 +1701,11 @@ static FAR struct usbhost_class_s *usbhost_create(FAR struct usbhost_hubport_s *
  *   desclen - The length in bytes of the configuration descriptor.
  *
  * Returned Value:
- *   On success, zero (OK) is returned. On a failure, a negated errno value is
- *   returned indicating the nature of the failure
+ *   On success, zero (OK) is returned. On a failure, a negated errno value
+ *   is returned indicating the nature of the failure
  *
- *   NOTE that the class instance remains valid upon return with a failure.  It is
- *   the responsibility of the higher level enumeration logic to call
+ *   NOTE that the class instance remains valid upon return with a failure.
+ *   It is the responsibility of the higher level enumeration logic to call
  *   CLASS_DISCONNECTED to free up the class driver resources.
  *
  * Assumptions:
@@ -1708,11 +1793,12 @@ static int usbhost_disconnected(struct usbhost_class_s *usbclass)
 
   /* Possibilities:
    *
-   * - Failure occurred before the controller poll task was started successfully.
-   *   In this case, the disconnection will have to be handled on the worker
-   *   task.
-   * - Failure occurred after the controller poll task was started successfully.  In
-   *   this case, the disconnection can be performed on the mouse poll thread.
+   * - Failure occurred before the controller poll task was started
+   *   successfully.  In this case, the disconnection will have to be
+   *   handled on the worker task.
+   * - Failure occurred after the controller poll task was started
+   *   successfully.  In this case, the disconnection can be performed on
+   *   the mouse poll thread.
    */
 
   if (priv->polling)
@@ -1766,11 +1852,15 @@ static int usbhost_open(FAR struct file *filep)
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* Check if the controller device is still connected.  We need to disable
-   * interrupts momentarily to assure that there are no asynchronous disconnect
-   * events.
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   flags = enter_critical_section();
@@ -1833,6 +1923,7 @@ static int usbhost_close(FAR struct file *filep)
   FAR struct inode *inode;
   FAR struct usbhost_state_s *priv;
   irqstate_t flags;
+  int ret;
 
   uinfo("Entry\n");
   DEBUGASSERT(filep && filep->f_inode);
@@ -1842,7 +1933,11 @@ static int usbhost_close(FAR struct file *filep)
   /* Decrement the reference count on the driver */
 
   DEBUGASSERT(priv->crefs >= 1);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
   /* We need to disable interrupts momentarily to assure that there are no
    * asynchronous poll or disconnect events.
@@ -1863,9 +1958,9 @@ static int usbhost_close(FAR struct file *filep)
        *
        * 1) It might be zero meaning that the polling thread has already
        *    exited and decremented its count.
-       * 2) If might be one meaning either that (a) the polling thread is still
-       *    running and still holds a count, or (b) the polling thread has exited,
-       *    but there is still an outstanding open reference.
+       * 2) If might be one meaning either that (a) the polling thread is
+       *    still running and still holds a count, or (b) the polling thread
+       *    has exited, but there is still an outstanding open reference.
        */
 
       if (priv->crefs == 0 || (priv->crefs == 1 && priv->polling))
@@ -1918,7 +2013,8 @@ 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_read(FAR struct file *filep, FAR char *buffer,
+                            size_t len)
 {
   FAR struct inode                          *inode;
   FAR struct usbhost_state_s                *priv;
@@ -1932,17 +2028,22 @@ static ssize_t usbhost_read(FAR struct file *filep, FAR char *buffer, size_t len
   /* 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);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
-  /* Check if the controller is still connected.  We need to disable interrupts
-   * momentarily to assure that there are no asynchronous disconnect events.
+  /* Check if the controller is still connected.  We need to disable
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   if (priv->disconnected)
     {
       /* No... the driver is no longer bound to the class.  That means that
-       * the USB controller is no longer connected.  Refuse any further attempts
-       * to access the driver.
+       * the USB controller is no longer connected.  Refuse any further
+       * attempts to access the driver.
        */
 
       ret = -ENODEV;
@@ -2035,15 +2136,16 @@ static int usbhost_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
   priv  = inode->i_private;
   hport = priv->usbclass.hport;
 
-  /* Check if the controller is still connected.  We need to disable interrupts
-   * momentarily to assure that there are no asynchronous disconnect events.
+  /* Check if the controller is still connected.  We need to disable
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   if (priv->disconnected)
     {
       /* No... the driver is no longer bound to the class.  That means that
-       * the USB controller is no longer connected.  Refuse any further attempts
-       * to access the driver.
+       * the USB controller is no longer connected.  Refuse any further
+       * attempts to access the driver.
        */
 
       ret = -ENODEV;
@@ -2103,7 +2205,7 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
 {
   FAR struct inode           *inode;
   FAR struct usbhost_state_s *priv;
-  int                         ret = OK;
+  int                         ret;
   int                         i;
 
   DEBUGASSERT(filep && filep->f_inode && fds);
@@ -2113,17 +2215,22 @@ static int usbhost_poll(FAR struct file *filep, FAR struct pollfd *fds,
   /* Make sure that we have exclusive access to the private data structure */
 
   DEBUGASSERT(priv);
-  usbhost_takesem(&priv->exclsem);
+  ret = usbhost_takesem(&priv->exclsem);
+  if (ret < 0)
+    {
+      return ret;
+    }
 
-  /* Check if the controller is still connected.  We need to disable interrupts
-   * momentarily to assure that there are no asynchronous disconnect events.
+  /* Check if the controller is still connected.  We need to disable
+   * interrupts momentarily to assure that there are no asynchronous
+   * disconnect events.
    */
 
   if (priv->disconnected)
     {
       /* No... the driver is no longer bound to the class.  That means that
-       * the USB controller is no longer connected.  Refuse any further attempts
-       * to access the driver.
+       * the USB controller is no longer connected.  Refuse any further
+       * attempts to access the driver.
        */
 
       ret = -ENODEV;


Mime
View raw message