Przeglądaj źródła

wait for scsi status complete before queueing for next scsi command

fix #207
hathach 6 lat temu
rodzic
commit
79fbc0b23c
1 zmienionych plików z 27 dodań i 18 usunięć
  1. 27 18
      src/class/msc/msc_device.c

+ 27 - 18
src/class/msc/msc_device.c

@@ -533,7 +533,18 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
       }
       }
     break;
     break;
 
 
-    case MSC_STAGE_STATUS: break; // processed immediately after this switch
+    case MSC_STAGE_STATUS:
+      // Wait for the command status wrapper complete event
+      if( (ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t)) )
+      {
+        // Move to default CMD stage
+        p_msc->stage = MSC_STAGE_CMD;
+
+        // Queue for the next CBW
+        TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
+      }
+    break;
+
     default : break;
     default : break;
   }
   }
 
 
@@ -543,32 +554,30 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
     if ( usbd_edpt_stalled(rhport,  p_msc->ep_in) || usbd_edpt_stalled(rhport,  p_msc->ep_out) )
     if ( usbd_edpt_stalled(rhport,  p_msc->ep_in) || usbd_edpt_stalled(rhport,  p_msc->ep_out) )
     {
     {
       // simulate an transfer complete with adjusted parameters --> this driver callback will fired again
       // simulate an transfer complete with adjusted parameters --> this driver callback will fired again
+      // and response with status phase after halted endpoints are cleared.
+      // note: use ep_out to prevent confusing with STATUS complete
       dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, XFER_RESULT_SUCCESS, false);
       dcd_event_xfer_complete(rhport, p_msc->ep_out, 0, XFER_RESULT_SUCCESS, false);
     }
     }
     else
     else
     {
     {
-      // Move to default CMD stage when sending status
-      p_msc->stage = MSC_STAGE_CMD;
-
       // Send SCSI Status
       // Send SCSI Status
-      TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)) );
+      TU_ASSERT(usbd_edpt_xfer(rhport, p_msc->ep_in , (uint8_t*) &p_msc->csw, sizeof(msc_csw_t)));
 
 
       // Invoke complete callback if defined
       // Invoke complete callback if defined
-      if ( SCSI_CMD_READ_10 == p_cbw->command[0])
-      {
-        if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun);
-      }
-      else if ( SCSI_CMD_WRITE_10 == p_cbw->command[0] )
-      {
-        if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun);
-      }
-      else
+      switch(p_cbw->command[0])
       {
       {
-        if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command);
-      }
+        case SCSI_CMD_READ_10:
+          if ( tud_msc_read10_complete_cb ) tud_msc_read10_complete_cb(p_cbw->lun);
+        break;
+
+        case SCSI_CMD_WRITE_10:
+          if ( tud_msc_write10_complete_cb ) tud_msc_write10_complete_cb(p_cbw->lun);
+        break;
 
 
-      // Queue for the next CBW
-      TU_ASSERT( usbd_edpt_xfer(rhport, p_msc->ep_out, (uint8_t*) &p_msc->cbw, sizeof(msc_cbw_t)) );
+        default:
+          if ( tud_msc_scsi_complete_cb ) tud_msc_scsi_complete_cb(p_cbw->lun, p_cbw->command);
+        break;
+      }
     }
     }
   }
   }