diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
index 6b7f519a24..374a1dc6dc 100644
--- a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
+++ b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
@@ -800,8 +800,10 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
 static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
                                struct pic32mx_ep_s *privep)
 {
+  volatile struct usbotg_bdtentry_s *bdtin;
   struct pic32mx_req_s *privreq;
   int bytesleft;
+  int epno;
 
   /* Check the request from the head of the endpoint request queue.  Since
    * we got here from a write completion event, the request queue should
@@ -809,38 +811,60 @@ static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
    */
 
   privreq = pic32mx_rqpeek(privep);
-  if (privreq != NULL)
+  DEBUGASSERT(privreq != NULL);
+
+  /* An outgoing IN packet has completed.  bdtin should point to the BDT
+   * that just completed.
+   */
+ 
+  bdtin = privep->bdtin;
+  epno   = USB_EPNO(privep->ep.eplog);
+
+  ullvdbg("EP%d: len=%d xfrd=%d [%p]\n",
+          epno, privreq->req.len, privreq->req.xfrd);
+  bdtdbg("EP%d BDT IN [%p] {%08x, %08x}\n",
+         epno, bdtin, bdtin->status, bdtin->addr);
+
+  /* We should own the BDT that just completed */
+
+  DEBUGASSERT((bdtin->status & USB_BDT_UOWN) == USB_BDT_COWN);
+
+  /* Toggle bdtin to the other BDT.  Is the current bdtin the EVEN bdt? */
+
+  privep->bdtin = &g_bdt[EP_IN_EVEN(epno)];
+  if (bdtin == privep->bdtin)
     {
-      /* An outgoing IN packet has completed. Update the number of bytes
-       * transferred.
-       */
-   
-      privreq->req.xfrd += privreq->inflight;
-      privreq->inflight  = 0;
-      bytesleft          = privreq->req.len - privreq->req.xfrd;
+      /* Yes.. Then the other BDT is the ODD BDT */
 
-      /* If all of the bytes were sent (bytesleft == 0) and no NULL packet is
-       * needed (!txnullpkt), then we are finished with the transfer
-       */
+      privep->bdtin++;
+    }
 
-      if (bytesleft == 0 && !privep->txnullpkt)
-        {
+  /* Update the number of bytes transferred. */
+   
+  privreq->req.xfrd += privreq->inflight;
+  privreq->inflight  = 0;
+  bytesleft          = privreq->req.len - privreq->req.xfrd;
+
+  /* If all of the bytes were sent (bytesleft == 0) and no NULL packet is
+   * needed (!txnullpkt), then we are finished with the transfer
+   */
 
-          /* The transfer is complete.  Give the completed request back to
-           * the class driver.
-          */
+  if (bytesleft == 0 && !privep->txnullpkt)
+    {
+      /* The transfer is complete.  Give the completed request back to
+       * the class driver.
+       */
 
-          usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
-          pic32mx_reqcomplete(privep, OK);
+      usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
+      pic32mx_reqcomplete(privep, OK);
 
-          /* Special case writes to endpoint zero.  If there is no transfer in
-           * progress, then we need to configure to received the next SETUP packet.
-          */
+      /* Special case writes to endpoint zero.  If there is no transfer in
+       * progress, then we need to configure to received the next SETUP packet.
+       */
 
-          if (USB_EPNO(privep->ep.eplog) == 0)
-            {
-              priv->ctrlstate = CTRLSTATE_WAITSETUP;
-            }
+      if (USB_EPNO(privep->ep.eplog) == 0)
+        {
+          priv->ctrlstate = CTRLSTATE_WAITSETUP;
         }
     }
 }
@@ -980,8 +1004,9 @@ static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv, struct pic32mx_ep_s
 static int pic32mx_rdcomplete(struct pic32mx_usbdev_s *priv,
                               struct pic32mx_ep_s *privep)
 {
-  volatile struct usbotg_bdtentry_s *bdtout = privep->bdtout;
+  volatile struct usbotg_bdtentry_s *bdtout;
   struct pic32mx_req_s *privreq;
+  int epno;
   int readlen;
 
   /* Check the request from the head of the endpoint request queue */
@@ -996,10 +1021,19 @@ static int pic32mx_rdcomplete(struct pic32mx_usbdev_s *priv,
       return -EINVAL;
     }
 
+  /* bdtout should point to the BDT that just completed */
+ 
+  bdtout = privep->bdtout;
+  epno   = USB_EPNO(privep->ep.eplog);
+
   ullvdbg("EP%d: len=%d xfrd=%d [%p]\n",
-          USB_EPNO(privep->ep.eplog), privreq->req.len, privreq->req.xfrd);
+          epno, privreq->req.len, privreq->req.xfrd);
   bdtdbg("EP%d BDT OUT [%p] {%08x, %08x}\n",
-         USB_EPNO(privep->ep.eplog), bdtout, bdtout->status, bdtout->addr);
+         epno, bdtout, bdtout->status, bdtout->addr);
+
+  /* We should own the BDT that just completed */
+
+  DEBUGASSERT((bdtout->status & USB_BDT_UOWN) == USB_BDT_COWN);
 
   /* Get the length of the data received from the BDT */
 
@@ -1020,6 +1054,16 @@ static int pic32mx_rdcomplete(struct pic32mx_usbdev_s *priv,
       pic32mx_reqcomplete(privep, OK);
     }
 
+  /* Toggle bdtout to the other BDT.  Is the current bdtout the EVEN bdt? */
+
+  privep->bdtout = &g_bdt[EP_OUT_EVEN(epno)];
+  if (bdtout == privep->bdtout)
+    {
+      /* Yes.. Then the other BDT is the ODD BDT */
+
+      privep->bdtout++;
+    }
+
   /* Set up the next read operation */
 
   return pic32mx_rdrequest(priv, privep);