/**
  ******************************************************************************
  * @file    usbh_msc_scsi.c 
  * @author  MCD Application Team
  * @version V2.1.0
  * @date    19-March-2012
  * @brief   This file implements the SCSI commands
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
  *
  * 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.
  *
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_ioreq.h"
#include "usbh_def.h"


/** @addtogroup USBH_LIB
  * @{
  */

/** @addtogroup USBH_CLASS
  * @{
  */

/** @addtogroup USBH_MSC_CLASS
  * @{
  */
  
/** @defgroup USBH_MSC_SCSI 
  * @brief    This file includes the mass storage related functions
  * @{
  */ 


/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
  * @{
  */ 

MassStorageParameter_TypeDef USBH_MSC_Param; 
/**
  * @}
  */ 

/** @defgroup USBH_MSC_SCSI_Private_Defines
  * @{
  */ 
/**
  * @}
  */ 

/** @defgroup USBH_MSC_SCSI_Private_Macros
  * @{
  */ 
/**
  * @}
  */ 


/** @defgroup USBH_MSC_SCSI_Private_Variables
  * @{
  */ 
  
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
    #pragma data_alignment=4   
  #endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataInBuffer[512] __ALIGN_END ;

#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
    #pragma data_alignment=4   
  #endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataOutBuffer[512] __ALIGN_END ;
/**
  * @}
  */ 


/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
  * @{
  */ 
/**
  * @}
  */ 


/** @defgroup USBH_MSC_SCSI_Exported_Variables
  * @{
  */ 

/**
  * @}
  */ 


/** @defgroup USBH_MSC_SCSI_Private_Functions
  * @{
  */ 




/**
  * @brief  USBH_MSC_TestUnitReady 
  *         Issues 'Test unit ready' command to the device. Once the response  
  *         received, it updates the status to upper layer.
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_TestUnitReady (USB_OTG_CORE_HANDLE *pdev)
{
  uint8_t index;
  USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  
  if(HCD_IsDeviceConnected(pdev))
  {  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:  
      /*Prepare the CBW and relevent field*/
      USBH_MSC_CBWData.field.CBWTransferLength = 0;       /* No Data Transfer */
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY;
      USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
      USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;
      USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_TEST_UNIT_READY;
      
      for(index = CBW_CB_LENGTH; index != 0; index--)
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_TEST_UNIT_READY; 
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      /* Start the transfer, then let the state 
      machine magage the other transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY; 
      break;
      
    case CMD_WAIT_STATUS: 
      if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
      { 
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
       
        status = USBH_MSC_OK;      
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_FAIL;
      }
      
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      }  
      break;
      
    default:
      break;
    }
  }
  return status;
}


/**
  * @brief  USBH_MSC_ReadCapacity10  
  *         Issue the read capacity command to the device. Once the response 
  *         received, it updates the status to upper layer
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev)
{
  uint8_t index;
  USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  
  if(HCD_IsDeviceConnected(pdev))
  {  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:
      /*Prepare the CBW and relevent field*/
      USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      
      USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
      USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_READ_CAPACITY10;
      
      for(index = CBW_CB_LENGTH; index != 0; index--)
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }    
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_READ_CAPACITY10; 
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      
      /* Start the transfer, then let the state machine manage the other 
                                                                transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      break;
      
    case CMD_WAIT_STATUS:
      if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
      {
        /*assign the capacity*/
        (((uint8_t*)&USBH_MSC_Param.MSCapacity )[3]) = USBH_DataInBuffer[0];
        (((uint8_t*)&USBH_MSC_Param.MSCapacity )[2]) = USBH_DataInBuffer[1];
        (((uint8_t*)&USBH_MSC_Param.MSCapacity )[1]) = USBH_DataInBuffer[2];
        (((uint8_t*)&USBH_MSC_Param.MSCapacity )[0]) = USBH_DataInBuffer[3];
        
        /*assign the page length*/
        (((uint8_t*)&USBH_MSC_Param.MSPageLength )[1]) = USBH_DataInBuffer[6];
        (((uint8_t*)&USBH_MSC_Param.MSPageLength )[0]) = USBH_DataInBuffer[7];
        
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_FAIL;
      }  
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      } 
      else
      {
        /* Wait for the Commands to get Completed */
        /* NO Change in state Machine */
      }
      break;
      
    default:
      break;
    }
  }
  return status;
}


/**
  * @brief  USBH_MSC_ModeSense6  
  *         Issue the Mode Sense6 Command to the device. This function is used 
  *          for reading the WriteProtect Status of the Mass-Storage device. 
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev)
{
  uint8_t index;
  USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  
  if(HCD_IsDeviceConnected(pdev))
  {  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:
      /*Prepare the CBW and relevent field*/
      USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      
      USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
      USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_MODE_SENSE6;
      
      for(index = CBW_CB_LENGTH; index != 0; index--)
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }    
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_MODE_SENSE6; 
      USBH_MSC_CBWData.field.CBWCB[2]  = MODE_SENSE_PAGE_CONTROL_FIELD | \
                                         MODE_SENSE_PAGE_CODE;
                                           
      USBH_MSC_CBWData.field.CBWCB[4]  = XFER_LEN_MODE_SENSE6;
                                                                                      
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      
      /* Start the transfer, then let the state machine manage the other 
                                                                transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      break;
      
    case CMD_WAIT_STATUS:
      if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
      {
        /* Assign the Write Protect status */
        /* If WriteProtect = 0, Writing is allowed 
           If WriteProtect != 0, Disk is Write Protected */
        if ( USBH_DataInBuffer[2] & MASK_MODE_SENSE_WRITE_PROTECT)
        {
          USBH_MSC_Param.MSWriteProtect   = DISK_WRITE_PROTECTED;
        }
        else
        {
          USBH_MSC_Param.MSWriteProtect   = 0;
        }
        
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_FAIL;
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      }
      else
      {
        /* Wait for the Commands to get Completed */
        /* NO Change in state Machine */
      }
      break;
      
    default:
      break;
    }
  }
  return status;
}

/**
  * @brief  USBH_MSC_RequestSense  
  *         Issues the Request Sense command to the device. Once the response 
  *         received, it updates the status to upper layer
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev)
{
  USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  
  uint8_t index;
  
  
  if(HCD_IsDeviceConnected(pdev))
  {  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:
      
      /*Prepare the CBW and relevent field*/
      USBH_MSC_CBWData.field.CBWTransferLength = \
                                                ALLOCATION_LENGTH_REQUEST_SENSE;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      
      USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
      USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent;
      USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_REQUEST_SENSE;
      

      for(index = CBW_CB_LENGTH; index != 0; index--)
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }    
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_REQUEST_SENSE; 
      USBH_MSC_CBWData.field.CBWCB[1]  = DESC_REQUEST_SENSE;
      USBH_MSC_CBWData.field.CBWCB[4]  = ALLOCATION_LENGTH_REQUEST_SENSE;
      
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      /* Start the transfer, then let the state machine magage 
      the other transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      
      break;
      
    case CMD_WAIT_STATUS:
      
      if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
      {
        /* Get Sense data*/
        (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[3]) = USBH_DataInBuffer[0];
        (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[2]) = USBH_DataInBuffer[1];
        (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[1]) = USBH_DataInBuffer[2];
        (((uint8_t*)&USBH_MSC_Param.MSSenseKey )[0]) = USBH_DataInBuffer[3];
        
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_FAIL;
      }
      
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      }
      
      else
      {
        /* Wait for the Commands to get Completed */
        /* NO Change in state Machine */
      }
      break;
      
    default:
      break;
    }
  }
  return status;
}


/**
  * @brief  USBH_MSC_Write10 
  *         Issue the write command to the device. Once the response received, 
  *         it updates the status to upper layer
  * @param  dataBuffer : DataBuffer contains the data to write
  * @param  address : Address to which the data will be written
  * @param  nbOfbytes : NbOfbytes to be written
  * @retval Status
  */
uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev, 
                         uint8_t *dataBuffer,
                         uint32_t address,
                         uint32_t nbOfbytes)
{
  uint8_t index;
  USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  uint16_t nbOfPages;
  
  if(HCD_IsDeviceConnected(pdev))
  {  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:   
      USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
      
      
      for(index = CBW_CB_LENGTH; index != 0; index--)  
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_WRITE10; 
      
      /*logical block address*/
      USBH_MSC_CBWData.field.CBWCB[2]  = (((uint8_t*)&address)[3]) ;
      USBH_MSC_CBWData.field.CBWCB[3]  = (((uint8_t*)&address)[2]);
      USBH_MSC_CBWData.field.CBWCB[4]  = (((uint8_t*)&address)[1]);
      USBH_MSC_CBWData.field.CBWCB[5]  = (((uint8_t*)&address)[0]);
      
      /*USBH_MSC_PAGE_LENGTH = 512*/
      nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH; 
      
      /*Tranfer length */
      USBH_MSC_CBWData.field.CBWCB[7]  = (((uint8_t *)&nbOfPages)[1]) ; 
      USBH_MSC_CBWData.field.CBWCB[8]  = (((uint8_t *)&nbOfPages)[0]) ; 
      
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      /* Start the transfer, then let the state machine 
      magage the other transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      
      break;
      
    case CMD_WAIT_STATUS:
      if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
      { 
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      }
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
      }
      
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      }
      break;
      
    default:
      break;
    }
  }
  return status;
}

/**
  * @brief  USBH_MSC_Read10 
  *         Issue the read command to the device. Once the response received, 
  *         it updates the status to upper layer
  * @param  dataBuffer : DataBuffer will contain the data to be read
  * @param  address : Address from which the data will be read
  * @param  nbOfbytes : NbOfbytes to be read
  * @retval Status
  */
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
                        uint8_t *dataBuffer,
                        uint32_t address,
                        uint32_t nbOfbytes)
{
  uint8_t index;
  static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  uint16_t nbOfPages;
  status = USBH_MSC_BUSY;
  
  if(HCD_IsDeviceConnected(pdev))
  {
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    {
    case CMD_SEND_STATE:
      /*Prepare the CBW and relevent field*/
      USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      
      USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
      
      for(index = CBW_CB_LENGTH; index != 0; index--)
      {
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      }
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_READ10; 
      
      /*logical block address*/
      
      USBH_MSC_CBWData.field.CBWCB[2]  = (((uint8_t*)&address)[3]);
      USBH_MSC_CBWData.field.CBWCB[3]  = (((uint8_t*)&address)[2]);
      USBH_MSC_CBWData.field.CBWCB[4]  = (((uint8_t*)&address)[1]);
      USBH_MSC_CBWData.field.CBWCB[5]  = (((uint8_t*)&address)[0]);
      
      /*USBH_MSC_PAGE_LENGTH = 512*/
      nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH;  
      
      /*Tranfer length */
      USBH_MSC_CBWData.field.CBWCB[7]  = (((uint8_t *)&nbOfPages)[1]) ; 
      USBH_MSC_CBWData.field.CBWCB[8]  = (((uint8_t *)&nbOfPages)[0]) ; 
      
      
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      /* Start the transfer, then let the state machine 
      magage the other transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      
      break;
      
    case CMD_WAIT_STATUS:
      
      if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \
        (HCD_IsDeviceConnected(pdev)))
      { 
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      }
      else if (( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) && \
        (HCD_IsDeviceConnected(pdev)))
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
      }
      
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      {
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      }
      else
      {
        /* Wait for the Commands to get Completed */
        /* NO Change in state Machine */
      }
      break;
      
    default:
      break;
    }
  }
  return status;
}


/**
  * @}
  */ 

/**
  * @}
  */ 

/**
  * @}
  */

/**
  * @}
  */ 

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



