diff --git a/drivers/usbdev/cdcacm.c b/drivers/usbdev/cdcacm.c
index 021136f90a..4023d2f2d6 100644
--- a/drivers/usbdev/cdcacm.c
+++ b/drivers/usbdev/cdcacm.c
@@ -63,6 +63,10 @@
 
 #include "cdcacm.h"
 
+#ifdef CONFIG_USBMSC_COMPOSITE
+#  include "composite.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -172,14 +176,17 @@ static void    cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
 
 /* USB class device ********************************************************/
 
-static int     cdcacm_bind(FAR struct usbdev_s *dev,
-                 FAR struct usbdevclass_driver_s *driver);
-static void    cdcacm_unbind(FAR struct usbdev_s *dev);
-static int     cdcacm_setup(FAR struct usbdev_s *dev,
-                 const struct usb_ctrlreq_s *ctrl);
-static void    cdcacm_disconnect(FAR struct usbdev_s *dev);
+static int     cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static void    cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static int     cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev,
+                 FAR const struct usb_ctrlreq_s *ctrl);
+static void    cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
 
-/* UART Operationt **********************************************************/
+/* UART Operations **********************************************************/
 
 static int     cdcuart_setup(FAR struct uart_dev_s *dev);
 static void    cdcuart_shutdown(FAR struct uart_dev_s *dev);
@@ -732,7 +739,7 @@ errout:
  ****************************************************************************/
 
 static void cdcacm_ep0incomplete(FAR struct usbdev_ep_s *ep,
-                                   FAR struct usbdev_req_s *req)
+                                 FAR struct usbdev_req_s *req)
 {
   if (req->result || req->xfrd != req->len)
     {
@@ -878,9 +885,10 @@ static void cdcacm_wrcomplete(FAR struct usbdev_ep_s *ep,
  *
  ****************************************************************************/
 
-static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int cdcacm_bind(FAR struct usbdevclass_driver_s *driver,
+                       FAR struct usbdev_s *dev)
 {
-  FAR struct cdcacm_dev_s *priv = ((struct cdcacm_driver_s*)driver)->dev;
+  FAR struct cdcacm_dev_s *priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
   FAR struct cdcacm_req_s *reqcontainer;
   irqstate_t flags;
   uint16_t reqlen;
@@ -892,7 +900,16 @@ static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
   /* Bind the structures */
 
   priv->usbdev   = dev;
+
+  /* Save the reference to our private data structure in EP0 so that it
+   * can be recovered in ep0 completion events (Unless we are part of 
+   * a composite device and, in that case, the composite device owns
+   * EP0).
+   */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
   dev->ep0->priv = priv;
+#endif
 
   /* Preallocate control request */
 
@@ -1010,7 +1027,7 @@ static int cdcacm_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
   return OK;
 
 errout:
-  cdcacm_unbind(dev);
+  cdcacm_unbind(driver, dev);
   return ret;
 }
 
@@ -1022,7 +1039,8 @@ errout:
  *
  ****************************************************************************/
 
-static void cdcacm_unbind(FAR struct usbdev_s *dev)
+static void cdcacm_unbind(FAR struct usbdevclass_driver_s *driver,
+                          FAR struct usbdev_s *dev)
 {
   FAR struct cdcacm_dev_s *priv;
   FAR struct cdcacm_req_s *reqcontainer;
@@ -1032,7 +1050,7 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSUNBIND, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return;
@@ -1041,7 +1059,7 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -1146,7 +1164,9 @@ static void cdcacm_unbind(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl)
+static int cdcacm_setup(FAR struct usbdevclass_driver_s *driver,
+                        FAR struct usbdev_s *dev,
+                        FAR const struct usb_ctrlreq_s *ctrl)
 {
   FAR struct cdcacm_dev_s *priv;
   FAR struct usbdev_req_s *ctrlreq;
@@ -1156,7 +1176,7 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
   int ret = -EOPNOTSUPP;
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0 || !ctrl)
+  if (!driver || !dev || !ctrl)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return -EIO;
@@ -1166,7 +1186,7 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
   /* Extract reference to private data */
 
   usbtrace(TRACE_CLASSSETUP, ctrl->req);
-  priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv || !priv->ctrlreq)
@@ -1465,9 +1485,21 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
 
   if (ret >= 0)
     {
+      /* Configure the response */
+
       ctrlreq->len   = MIN(len, ret);
       ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
-      ret            = EP_SUBMIT(dev->ep0, ctrlreq);
+
+      /* Send the response -- either directly to the USB controller or
+       * indirectly in the case where this class is a member of a composite
+       * device.
+       */
+
+#ifndef CONFIG_CDCACM_COMPOSITE
+      ret = EP_SUBMIT(dev->ep0, ctrlreq);
+#else
+      ret = composite_ep0submit(driver, dev, ctrlreq);
+#endif
       if (ret < 0)
         {
           usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -1488,7 +1520,8 @@ static int cdcacm_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ct
  *
  ****************************************************************************/
 
-static void cdcacm_disconnect(FAR struct usbdev_s *dev)
+static void cdcacm_disconnect(FAR struct usbdevclass_driver_s *driver,
+                              FAR struct usbdev_s *dev)
 {
   FAR struct cdcacm_dev_s *priv;
   irqstate_t flags;
@@ -1496,7 +1529,7 @@ static void cdcacm_disconnect(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSDISCONNECT, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return;
@@ -1505,7 +1538,7 @@ static void cdcacm_disconnect(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct cdcacm_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct cdcacm_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -2092,7 +2125,7 @@ void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev)
 
   if (priv->usbdev)
     {
-       cdcacm_unbind(Fpriv->usbdev);
+       cdcacm_unbind(classdev, priv->usbdev);
     }
 
   /* Unregister the driver (unless we are a part of a composite device */
diff --git a/drivers/usbdev/composite.c b/drivers/usbdev/composite.c
index 75f0fbed14..c689f1b667 100644
--- a/drivers/usbdev/composite.c
+++ b/drivers/usbdev/composite.c
@@ -67,7 +67,7 @@
 
 struct composite_dev_s
 {
-  FAR struct usbdev_s         *usbdev;  /* usbdev driver pointer */
+  FAR struct usbdev_s         *usbdev;   /* usbdev driver pointer */
   uint8_t                      config;   /* Configuration number */
   FAR struct usbdev_req_s     *ctrlreq;  /* Allocated control request */
   struct usbdevclass_driver_s *dev1;     /* Device 1 class object */
@@ -107,14 +107,19 @@ static void    composite_freereq(FAR struct usbdev_ep_s *ep,
 
 /* USB class device ********************************************************/
 
-static int     composite_bind(FAR struct usbdev_s *dev,
-                 FAR struct usbdevclass_driver_s *driver);
-static void    composite_unbind(FAR struct usbdev_s *dev);
-static int     composite_setup(FAR struct usbdev_s *dev,
+static int     composite_bind(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev)
+static void    composite_unbind(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static int     composite_setup(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev,
                  FAR const struct usb_ctrlreq_s *ctrl);
-static void    composite_disconnect(FAR struct usbdev_s *dev);
-static void    composite_suspend(FAR struct usbdev_s *dev);
-static void    composite_resume(FAR struct usbdev_s *dev);
+static void    composite_disconnect(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static void    composite_suspend(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static void    composite_resume(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
 
 /****************************************************************************
  * Private Data
@@ -150,13 +155,15 @@ const char g_compserialstr[]  = CONFIG_COMPOSITE_SERIALSTR;
  * Name: composite_ep0incomplete
  *
  * Description:
- *   Handle completion of EP0 control operations
+ *   Handle completion of the composite driver's EP0 control operations
  *
  ****************************************************************************/
 
 static void composite_ep0incomplete(FAR struct usbdev_ep_s *ep,
                                     FAR struct usbdev_req_s *req)
 {
+  /* Just check the result of the transfer */
+
   if (req->result || req->xfrd != req->len)
     {
       usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_REQRESULT), (uint16_t)-req->result);
@@ -254,9 +261,10 @@ static void composite_freereq(FAR struct usbdev_ep_s *ep,
  *
  ****************************************************************************/
 
-static int composite_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int composite_bind(FAR struct usbdevclass_driver_s *driver,
+                          FAR struct usbdev_s *dev)
 {
-  FAR struct composite_dev_s *priv = ((struct composite_driver_s*)driver)->dev;
+  FAR struct composite_dev_s *priv = ((FAR struct composite_driver_s*)driver)->dev;
   int ret;
 
   usbtrace(TRACE_CLASSBIND, 0);
@@ -264,9 +272,14 @@ static int composite_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_drive
   /* Bind the structures */
 
   priv->usbdev   = dev;
+
+  /* Save the reference to our private data structure in EP0 so that it
+   * can be recovered in ep0 completion events.
+   */
+
   dev->ep0->priv = priv;
 
-  /* Preallocate control request */
+  /* Preallocate one control request */
 
   priv->ctrlreq = composite_allocreq(dev->ep0, COMPOSITE_CFGDESCSIZE);
   if (priv->ctrlreq == NULL)
@@ -318,7 +331,8 @@ errout:
  *
  ****************************************************************************/
 
-static void composite_unbind(FAR struct usbdev_s *dev)
+static void composite_unbind(FAR struct usbdevclass_driver_s *driver,
+                             FAR struct usbdev_s *dev)
 {
   FAR struct composite_dev_s *priv;
   irqstate_t flags;
@@ -326,7 +340,7 @@ static void composite_unbind(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSUNBIND, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
       return;
@@ -335,7 +349,7 @@ static void composite_unbind(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct composite_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -376,7 +390,8 @@ static void composite_unbind(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static int composite_setup(FAR struct usbdev_s *dev,
+static int composite_setup(FAR struct usbdevclass_driver_s *driver,
+                           FAR struct usbdev_s *dev,
                            FAR const struct usb_ctrlreq_s *ctrl)
 {
   FAR struct composite_dev_s *priv;
@@ -388,7 +403,7 @@ static int composite_setup(FAR struct usbdev_s *dev,
   int ret = -EOPNOTSUPP;
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0 || !ctrl)
+  if (!driver || !dev || !dev->ep0 || !ctrl)
     {
       usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_SETUPINVALIDARGS), 0);
       return -EIO;
@@ -398,7 +413,7 @@ static int composite_setup(FAR struct usbdev_s *dev,
   /* Extract a reference to private data */
 
   usbtrace(TRACE_CLASSSETUP, ctrl->req);
-  priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct composite_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -562,9 +577,14 @@ static int composite_setup(FAR struct usbdev_s *dev,
 
   if (ret >= 0 && !dispatched)
     {
+      /* Setup the request */
+
       ctrlreq->len   = MIN(len, ret);
       ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
-      ret            = EP_SUBMIT(dev->ep0, ctrlreq);
+
+      /* And submit the request to the USB controller driver */
+
+      ret = EP_SUBMIT(dev->ep0, ctrlreq);
       if (ret < 0)
         {
           usbtrace(TRACE_CLSERROR(COMPOSITE_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -585,7 +605,8 @@ static int composite_setup(FAR struct usbdev_s *dev,
  *
  ****************************************************************************/
 
-static void composite_disconnect(FAR struct usbdev_s *dev)
+static void composite_disconnect(FAR struct usbdevclass_driver_s *driver,
+                                 FAR struct usbdev_s *dev)
 {
   FAR struct composite_dev_s *priv;
   irqstate_t flags;
@@ -593,7 +614,7 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSDISCONNECT, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev)
     {
       usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
       return;
@@ -602,7 +623,7 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct composite_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -637,7 +658,8 @@ static void composite_disconnect(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static void composite_suspend(FAR struct usbdev_s *dev)
+static void composite_suspend(FAR struct usbdevclass_driver_s *driver,
+                              FAR struct usbdev_s *dev)
 {
   FAR struct composite_dev_s *priv;
   irqstate_t flags;
@@ -645,7 +667,7 @@ static void composite_suspend(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSSUSPEND, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0 || !dev->ep0->priv)
+  if (!dev)
     {
       usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
       return;
@@ -654,7 +676,15 @@ static void composite_suspend(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct composite_driver_s*)driver)->dev;
+
+#ifdef CONFIG_DEBUG
+  if (!priv)
+    {
+      usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
+      return;
+    }
+#endif
 
   /* Forward the suspend event to the constituent devices */
 
@@ -672,15 +702,14 @@ static void composite_suspend(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static void composite_resume(FAR struct usbdev_s *dev)
+static void composite_resume(FAR struct usbdevclass_driver_s *driver,
+                             FAR struct usbdev_s *dev)
 {
   FAR struct composite_dev_s *priv = NULL;
   irqstate_t flags;
 
-  if (!dev || !dev->ep0 || !dev->ep0->priv)
-
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!dev)
     {
       usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_INVALIDARG), 0);
       return;
@@ -689,7 +718,15 @@ static void composite_resume(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct composite_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct composite_driver_s*)driver)->dev;
+
+#ifdef CONFIG_DEBUG
+  if (!priv)
+    {
+      usbtrace(TRACE_CLSERROR(USBCOMPOSITE_TRACEERR_EP0NOTBOUND), 0);
+      return;
+    }
+#endif
 
   /* Forward the resume event to the constituent devices */
 
@@ -784,4 +821,27 @@ errout_with_alloc:
   return ret;
 }
 
+/****************************************************************************
+ * Name: composite_ep0submit
+ *
+ * Description:
+ *   Members of the composite cannot send on EP0 directly because EP0 is
+ *   is "owned" by the composite device.  Instead, when configured as members
+ *   of a composite device, those classes should call this method so that
+ *   the composite device can send on EP0 onbehalf of the class.
+ *
+ ****************************************************************************/
+
+int composite_ep0submit(FAR struct usbdevclass_driver_s *driver,
+                        FAR struct usbdev_s *dev,
+                        FAR struct usbdev_req_s *ctrlreq)
+{
+  /* This function is not really necessary in the current design.  However,
+   * keeping this will provide us a little flexibility in the future if
+   * it becomes necessary to manage the completion callbacks.
+   */
+
+   return EP_SUBMIT(dev->ep0, ctrlreq);
+}
+
 #endif /* CONFIG_USBDEV_COMPOSITE */
diff --git a/drivers/usbdev/composite.h b/drivers/usbdev/composite.h
index 114754ec4e..4cd3ac6064 100644
--- a/drivers/usbdev/composite.h
+++ b/drivers/usbdev/composite.h
@@ -253,7 +253,22 @@ extern const char g_compserialstr[];
  ****************************************************************************/
 
 /****************************************************************************
- * Name: usbmsc_mkstrdesc
+ * Name: composite_ep0submit
+ *
+ * Description:
+ *   Members of the composite cannot send on EP0 directly because EP0 is
+ *   is "owned" by the composite device.  Instead, when configured as members
+ *   of a composite device, those classes should call this method so that
+ *   the composite device can send on EP0 onbehalf of the class.
+ *
+ ****************************************************************************/
+
+int composite_ep0submit(FAR struct usbdevclass_driver_s *driver,
+                        FAR struct usbdev_s *dev,
+                        FAR struct usbdev_req_s *ctrlreq);
+
+/****************************************************************************
+ * Name: composite_mkstrdesc
  *
  * Description:
  *   Construct a string descriptor
diff --git a/drivers/usbdev/pl2303.c b/drivers/usbdev/pl2303.c
index 9759b714d3..81c3376dc2 100644
--- a/drivers/usbdev/pl2303.c
+++ b/drivers/usbdev/pl2303.c
@@ -303,7 +303,7 @@ static inline int usbclass_recvpacket(FAR struct pl2303_dev_s *priv,
 
 /* Request helpers *********************************************************/
 
-static struct usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
+static struct  usbdev_req_s *usbclass_allocreq(FAR struct usbdev_ep_s *ep,
                  uint16_t len);
 static void    usbclass_freereq(FAR struct usbdev_ep_s *ep,
                  FAR struct usbdev_req_s *req);
@@ -333,22 +333,25 @@ static void    usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
 
 /* USB class device ********************************************************/
 
-static int     usbclass_bind(FAR struct usbdev_s *dev,
-                 FAR struct usbdevclass_driver_s *driver);
-static void    usbclass_unbind(FAR struct usbdev_s *dev);
-static int     usbclass_setup(FAR struct usbdev_s *dev,
-                 const struct usb_ctrlreq_s *ctrl);
-static void    usbclass_disconnect(FAR struct usbdev_s *dev);
+static int     usbclass_bind(FAR struct usbdevclass_driver_s *driver, 
+                 FAR struct usbdev_s *dev);
+static void    usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
+static int     usbclass_setup(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev,
+                 FAR const struct usb_ctrlreq_s *ctrl);
+static void    usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
+                 FAR struct usbdev_s *dev);
 
 /* Serial port *************************************************************/
 
-static int     pl2303_setup(FAR struct uart_dev_s *dev);
-static void    pl2303_shutdown(FAR struct uart_dev_s *dev);
-static int     pl2303_attach(FAR struct uart_dev_s *dev);
-static void    pl2303_detach(FAR struct uart_dev_s *dev);
-static void    pl2303_rxint(FAR struct uart_dev_s *dev, bool enable);
-static void    pl2303_txint(FAR struct uart_dev_s *dev, bool enable);
-static bool    pl2303_txempty(FAR struct uart_dev_s *dev);
+static int     usbser_setup(FAR struct uart_dev_s *dev);
+static void    usbser_shutdown(FAR struct uart_dev_s *dev);
+static int     usbser_attach(FAR struct uart_dev_s *dev);
+static void    usbser_detach(FAR struct uart_dev_s *dev);
+static void    usbser_rxint(FAR struct uart_dev_s *dev, bool enable);
+static void    usbser_txint(FAR struct uart_dev_s *dev, bool enable);
+static bool    usbser_txempty(FAR struct uart_dev_s *dev);
 
 /****************************************************************************
  * Private Variables
@@ -370,18 +373,18 @@ static const struct usbdevclass_driverops_s g_driverops =
 
 static const struct uart_ops_s g_uartops =
 {
-  pl2303_setup,         /* setup */
-  pl2303_shutdown,      /* shutdown */
-  pl2303_attach,        /* attach */
-  pl2303_detach,        /* detach */
+  usbser_setup,         /* setup */
+  usbser_shutdown,      /* shutdown */
+  usbser_attach,        /* attach */
+  usbser_detach,        /* detach */
   NULL,                 /* ioctl */
   NULL,                 /* receive */
-  pl2303_rxint,         /* rxinit */
+  usbser_rxint,         /* rxinit */
   NULL,                 /* rxavailable */
   NULL,                 /* send */
-  pl2303_txint,         /* txinit */
+  usbser_txint,         /* txinit */
   NULL,                 /* txready */
-  pl2303_txempty        /* txempty */
+  usbser_txempty        /* txempty */
 };
 
 /* USB descriptor templates these will be copied and modified **************/
@@ -1265,9 +1268,10 @@ static void usbclass_wrcomplete(FAR struct usbdev_ep_s *ep,
  *
  ****************************************************************************/
 
-static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int usbclass_bind(FAR struct usbdevclass_driver_s *driver,
+                         FAR struct usbdev_s *dev)
 {
-  FAR struct pl2303_dev_s *priv = ((struct pl2303_driver_s*)driver)->dev;
+  FAR struct pl2303_dev_s *priv = ((FAR struct pl2303_driver_s*)driver)->dev;
   FAR struct pl2303_req_s *reqcontainer;
   irqstate_t flags;
   uint16_t reqlen;
@@ -1279,6 +1283,13 @@ static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver
   /* Bind the structures */
 
   priv->usbdev   = dev;
+
+  /* Save the reference to our private data structure in EP0 so that it
+   * can be recovered in ep0 completion events (Unless we are part of 
+   * a composite device and, in that case, the composite device owns
+   * EP0).
+   */
+
   dev->ep0->priv = priv;
 
   /* Preallocate control request */
@@ -1393,7 +1404,7 @@ static int usbclass_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver
   return OK;
 
 errout:
-  usbclass_unbind(dev);
+  usbclass_unbind(driver, dev);
   return ret;
 }
 
@@ -1405,7 +1416,8 @@ errout:
  *
  ****************************************************************************/
 
-static void usbclass_unbind(FAR struct usbdev_s *dev)
+static void usbclass_unbind(FAR struct usbdevclass_driver_s *driver,
+                            FAR struct usbdev_s *dev)
 {
   FAR struct pl2303_dev_s *priv;
   FAR struct pl2303_req_s *reqcontainer;
@@ -1415,7 +1427,7 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSUNBIND, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return;
@@ -1424,7 +1436,7 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct pl2303_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -1529,7 +1541,9 @@ static void usbclass_unbind(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl)
+static int usbclass_setup(FAR struct usbdevclass_driver_s *driver,
+                          FAR struct usbdev_s *dev,
+                          FAR const struct usb_ctrlreq_s *ctrl)
 {
   FAR struct pl2303_dev_s *priv;
   FAR struct usbdev_req_s *ctrlreq;
@@ -1539,7 +1553,7 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
   int ret = -EOPNOTSUPP;
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0 || !ctrl)
+  if (!driver || !dev || !dev->ep0 || !ctrl)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return -EIO;
@@ -1549,7 +1563,7 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
   /* Extract reference to private data */
 
   usbtrace(TRACE_CLASSSETUP, ctrl->req);
-  priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct pl2303_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv || !priv->ctrlreq)
@@ -1791,7 +1805,8 @@ static int usbclass_setup(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *
  *
  ****************************************************************************/
 
-static void usbclass_disconnect(FAR struct usbdev_s *dev)
+static void usbclass_disconnect(FAR struct usbdevclass_driver_s *driver,
+                                FAR struct usbdev_s *dev)
 {
   FAR struct pl2303_dev_s *priv;
   irqstate_t flags;
@@ -1799,7 +1814,7 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSDISCONNECT, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBSER_TRACEERR_INVALIDARG), 0);
       return;
@@ -1808,7 +1823,7 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct pl2303_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct pl2303_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -1841,14 +1856,14 @@ static void usbclass_disconnect(FAR struct usbdev_s *dev)
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pl2303_setup
+ * Name: usbser_setup
  *
  * Description:
  *   This method is called the first time that the serial port is opened.
  *
  ****************************************************************************/
 
-static int pl2303_setup(FAR struct uart_dev_s *dev)
+static int usbser_setup(FAR struct uart_dev_s *dev)
 {
   FAR struct pl2303_dev_s *priv;
 
@@ -1880,18 +1895,18 @@ static int pl2303_setup(FAR struct uart_dev_s *dev)
 }
 
 /****************************************************************************
- * Name: pl2303_shutdown
+ * Name: usbser_shutdown
  *
  * Description:
  *   This method is called when the serial port is closed.  This operation
  *   is very simple for the USB serial backend because the serial driver
  *   has already assured that the TX data has full drained -- it calls
- *   pl2303_txempty() until that function returns true before calling this
+ *   usbser_txempty() until that function returns true before calling this
  *   function.
  *
  ****************************************************************************/
 
-static void pl2303_shutdown(FAR struct uart_dev_s *dev)
+static void usbser_shutdown(FAR struct uart_dev_s *dev)
 {
   usbtrace(PL2303_CLASSASPI_SHUTDOWN, 0);
 
@@ -1906,50 +1921,50 @@ static void pl2303_shutdown(FAR struct uart_dev_s *dev)
 }
 
 /****************************************************************************
- * Name: pl2303_attach
+ * Name: usbser_attach
  *
  * Description:
  *   Does not apply to the USB serial class device
  *
  ****************************************************************************/
 
-static int pl2303_attach(FAR struct uart_dev_s *dev)
+static int usbser_attach(FAR struct uart_dev_s *dev)
 {
   usbtrace(PL2303_CLASSASPI_ATTACH, 0);
   return OK;
 }
 
 /****************************************************************************
- * Name: pl2303_detach
+ * Name: usbser_detach
  *
  * Description:
 *   Does not apply to the USB serial class device
   *
  ****************************************************************************/
 
-static void pl2303_detach(FAR struct uart_dev_s *dev)
+static void usbser_detach(FAR struct uart_dev_s *dev)
 {
   usbtrace(PL2303_CLASSASPI_DETACH, 0);
 }
 
 /****************************************************************************
- * Name: pl2303_rxint
+ * Name: usbser_rxint
  *
  * Description:
  *   Called by the serial driver to enable or disable RX interrupts.  We, of
  *   course, have no RX interrupts but must behave consistently.  This method
  *   is called under the conditions:
  *
- *   1. With enable==true when the port is opened (just after pl2303_setup
- *      and pl2303_attach are called called)
+ *   1. With enable==true when the port is opened (just after usbser_setup
+ *      and usbser_attach are called called)
  *   2. With enable==false while transferring data from the RX buffer
  *   2. With enable==true while waiting for more incoming data
- *   3. With enable==false when the port is closed (just before pl2303_detach
- *      and pl2303_shutdown are called).
+ *   3. With enable==false when the port is closed (just before usbser_detach
+ *      and usbser_shutdown are called).
  *
  ****************************************************************************/
 
-static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
+static void usbser_rxint(FAR struct uart_dev_s *dev, bool enable)
 {
   FAR struct pl2303_dev_s *priv;
   FAR uart_dev_t *serdev;
@@ -2029,7 +2044,7 @@ static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
 }
 
 /****************************************************************************
- * Name: pl2303_txint
+ * Name: usbser_txint
  *
  * Description:
  *   Called by the serial driver to enable or disable TX interrupts.  We, of
@@ -2042,7 +2057,7 @@ static void pl2303_rxint(FAR struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
-static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
+static void usbser_txint(FAR struct uart_dev_s *dev, bool enable)
 {
   FAR struct pl2303_dev_s *priv;
 
@@ -2076,7 +2091,7 @@ static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
 }
 
 /****************************************************************************
- * Name: pl2303_txempty
+ * Name: usbser_txempty
  *
  * Description:
  *   Return true when all data has been sent.  This is called from the
@@ -2087,7 +2102,7 @@ static void pl2303_txint(FAR struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
-static bool pl2303_txempty(FAR struct uart_dev_s *dev)
+static bool usbser_txempty(FAR struct uart_dev_s *dev)
 {
   FAR struct pl2303_dev_s *priv = (FAR struct pl2303_dev_s*)dev->priv;
 
diff --git a/drivers/usbdev/usbmsc.c b/drivers/usbdev/usbmsc.c
index e99342abc6..3efa1e3db2 100644
--- a/drivers/usbdev/usbmsc.c
+++ b/drivers/usbdev/usbmsc.c
@@ -82,6 +82,10 @@
 
 #include "usbmsc.h"
 
+#ifdef CONFIG_USBMSC_COMPOSITE
+#  include "composite.h"
+#endif
+
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
@@ -121,12 +125,15 @@ static void   usbmsc_freereq(FAR struct usbdev_ep_s *ep,
 
 /* Class Driver Operations (most at interrupt level) ************************/
 
-static int    usbmsc_bind(FAR struct usbdev_s *dev,
-                FAR struct usbdevclass_driver_s *driver);
-static void   usbmsc_unbind(FAR struct usbdev_s *dev);
-static int    usbmsc_setup(FAR struct usbdev_s *dev,
+static int    usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
+                FAR struct usbdev_s *dev);
+static void   usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
+                FAR struct usbdev_s *dev);
+static int    usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
+                FAR struct usbdev_s *dev,
                 FAR const struct usb_ctrlreq_s *ctrl);
-static void   usbmsc_disconnect(FAR struct usbdev_s *dev);
+static void   usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
+                FAR struct usbdev_s *dev);
 
 /* Initialization/Uninitialization ******************************************/
 
@@ -235,9 +242,10 @@ static void usbmsc_freereq(FAR struct usbdev_ep_s *ep, struct usbdev_req_s *req)
  *
  ****************************************************************************/
 
-static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver)
+static int usbmsc_bind(FAR struct usbdevclass_driver_s *driver,
+                       FAR struct usbdev_s *dev)
 {
-  FAR struct usbmsc_dev_s *priv = ((struct usbmsc_driver_s*)driver)->dev;
+  FAR struct usbmsc_dev_s *priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
   FAR struct usbmsc_req_s *reqcontainer;
   irqstate_t flags;
   int ret = OK;
@@ -248,7 +256,16 @@ static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
   /* Bind the structures */
 
   priv->usbdev   = dev;
+
+  /* Save the reference to our private data structure in EP0 so that it
+   * can be recovered in ep0 completion events (Unless we are part of 
+   * a composite device and, in that case, the composite device owns
+   * EP0).
+   */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
   dev->ep0->priv = priv;
+#endif
 
   /* The configured EP0 size should match the reported EP0 size.  We could
    * easily adapt to the reported EP0 size, but then we could not use the
@@ -351,7 +368,7 @@ static int usbmsc_bind(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s
   return OK;
 
 errout:
-  usbmsc_unbind(dev);
+  usbmsc_unbind(driver, dev);
   return ret;
 }
 
@@ -363,7 +380,8 @@ errout:
  *
  ****************************************************************************/
 
-static void usbmsc_unbind(FAR struct usbdev_s *dev)
+static void usbmsc_unbind(FAR struct usbdevclass_driver_s *driver,
+                          FAR struct usbdev_s *dev)
 {
   FAR struct usbmsc_dev_s *priv;
   FAR struct usbmsc_req_s *reqcontainer;
@@ -373,7 +391,7 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSUNBIND, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_UNBINDINVALIDARGS), 0);
       return;
@@ -382,7 +400,7 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct usbmsc_driver_s*)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
@@ -477,7 +495,8 @@ static void usbmsc_unbind(FAR struct usbdev_s *dev)
  *
  ****************************************************************************/
 
-static int usbmsc_setup(FAR struct usbdev_s *dev,
+static int usbmsc_setup(FAR struct usbdevclass_driver_s *driver,
+                        FAR struct usbdev_s *dev,
                         FAR const struct usb_ctrlreq_s *ctrl)
 {
   FAR struct usbmsc_dev_s *priv;
@@ -488,7 +507,7 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
   int ret = -EOPNOTSUPP;
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0 || !ctrl)
+  if (!driver || !dev || !dev->ep0 || !ctrl)
     {
       usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_SETUPINVALIDARGS), 0);
       return -EIO;
@@ -498,7 +517,7 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
   /* Extract reference to private data */
 
   usbtrace(TRACE_CLASSSETUP, ctrl->req);
-  priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv || !priv->ctrlreq)
@@ -763,9 +782,21 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
 
   if (ret >= 0)
     {
+      /* Configure the response */
+
       ctrlreq->len   = MIN(len, ret);
       ctrlreq->flags = USBDEV_REQFLAGS_NULLPKT;
-      ret            = EP_SUBMIT(dev->ep0, ctrlreq);
+
+      /* Send the response -- either directly to the USB controller or
+       * indirectly in the case where this class is a member of a composite
+       * device.
+       */
+
+#ifndef CONFIG_USBMSC_COMPOSITE
+      ret = EP_SUBMIT(dev->ep0, ctrlreq);
+#else
+      ret = composite_ep0submit(driver, dev, ctrlreq);
+#endif
       if (ret < 0)
         {
           usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_EPRESPQ), (uint16_t)-ret);
@@ -789,7 +820,8 @@ static int usbmsc_setup(FAR struct usbdev_s *dev,
  *
  ****************************************************************************/
 
-static void usbmsc_disconnect(FAR struct usbdev_s *dev)
+static void usbmsc_disconnect(FAR struct usbdevclass_driver_s *driver,
+                              FAR struct usbdev_s *dev)
 {
   struct usbmsc_dev_s *priv;
   irqstate_t flags;
@@ -797,7 +829,7 @@ static void usbmsc_disconnect(FAR struct usbdev_s *dev)
   usbtrace(TRACE_CLASSDISCONNECT, 0);
 
 #ifdef CONFIG_DEBUG
-  if (!dev || !dev->ep0)
+  if (!driver || !dev || !dev->ep0)
     {
       usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_DISCONNECTINVALIDARGS), 0);
       return;
@@ -806,7 +838,7 @@ static void usbmsc_disconnect(FAR struct usbdev_s *dev)
 
   /* Extract reference to private data */
 
-  priv = (FAR struct usbmsc_dev_s *)dev->ep0->priv;
+  priv = ((FAR struct usbmsc_driver_s *)driver)->dev;
 
 #ifdef CONFIG_DEBUG
   if (!priv)
diff --git a/include/nuttx/usb/usbdev.h b/include/nuttx/usb/usbdev.h
index 8e89eddab9..a727573c37 100644
--- a/include/nuttx/usb/usbdev.h
+++ b/include/nuttx/usb/usbdev.h
@@ -1,8 +1,8 @@
 /************************************************************************************
  * include/nuttx/usb/usbdev.h
  *
- *   Copyright (C) 2008-2010 Gregory Nutt. All rights reserved.
- *   Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *   Copyright (C) 2008-2010, 2012 Gregory Nutt. All rights reserved.
+ *   Author: Gregory Nutt <gnutt@nuttx.org>
  *
  * NOTE:  This interface was inspired by the Linux gadget interface by
  * David Brownell. That work was very helpful in determining a usable
@@ -151,29 +151,29 @@
 
 /* Invoked when the driver is bound to a USB device driver. */
 
-#define CLASS_BIND(drvr,dev)      (drvr)->ops->bind(dev, drvr)
+#define CLASS_BIND(drvr,dev)      (drvr)->ops->bind(drvr,dev)
 
 /* Invoked when the driver is unbound from a USB device driver */
 
-#define CLASS_UNBIND(drvr,dev)    (drvr)->ops->unbind(dev)
+#define CLASS_UNBIND(drvr,dev)    (drvr)->ops->unbind(drvr,dev)
 
 /* Invoked after all transfers have been stopped, when the host is disconnected. */
 
-#define CLASS_DISCONNECT(drvr,dev) (drvr)->ops->disconnect(dev)
+#define CLASS_DISCONNECT(drvr,dev) (drvr)->ops->disconnect(drvr,dev)
 
 /* Invoked for ep0 control requests */
 
-#define CLASS_SETUP(drvr,dev,ctrl) (drvr)->ops->setup(dev, ctrl)
+#define CLASS_SETUP(drvr,dev,ctrl) (drvr)->ops->setup(drvr,dev,ctrl)
 
 /* Invoked on USB suspend. */
 
 #define CLASS_SUSPEND(drvr,dev)   \
-  do { if ((drvr)->ops->suspend) (drvr)->ops->suspend(dev); } while (0)
+  do { if ((drvr)->ops->suspend) (drvr)->ops->suspend(drvr,dev); } while (0)
 
 /* Invoked on USB resume */
 
 #define CLASS_RESUME(drvr,dev)  \
-  do { if ((drvr)->ops->resume) (drvr)->ops->resume(dev); } while (0)
+  do { if ((drvr)->ops->resume) (drvr)->ops->resume(drvr,dev); } while (0)
 
 /* Device speeds */
 
@@ -260,7 +260,8 @@ struct usbdev_ops_s
 {
   /* Allocate and free endpoints */
 
-  FAR struct usbdev_ep_s *(*allocep)(FAR struct usbdev_s *dev, uint8_t epphy, bool in, uint8_t eptype);
+  FAR struct usbdev_ep_s *(*allocep)(FAR struct usbdev_s *dev, uint8_t epphy,
+                                     bool in, uint8_t eptype);
   void (*freeep)(FAR struct usbdev_s *dev, FAR struct usbdev_ep_s *ep);
 
   /* Get the frame number from the last SOF */
@@ -291,12 +292,14 @@ struct usbdev_s
 struct usbdevclass_driver_s;
 struct usbdevclass_driverops_s
 {
-  int  (*bind)(FAR struct usbdev_s *dev, FAR struct usbdevclass_driver_s *driver);
-  void (*unbind)(FAR struct usbdev_s *dev);
-  int  (*setup)(FAR struct usbdev_s *dev, const struct usb_ctrlreq_s *ctrl);
-  void (*disconnect)(FAR struct usbdev_s *dev);
-  void (*suspend)(FAR struct usbdev_s *dev);
-  void (*resume)(FAR struct usbdev_s *dev);
+  int  (*bind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+  void (*unbind)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+  int  (*setup)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev,
+          FAR const struct usb_ctrlreq_s *ctrl);
+  void (*disconnect)(FAR struct usbdevclass_driver_s *driver,
+          FAR struct usbdev_s *dev);
+  void (*suspend)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
+  void (*resume)(FAR struct usbdevclass_driver_s *driver, FAR struct usbdev_s *dev);
 };
 
 struct usbdevclass_driver_s