Merge branch 'tmaster' into future
[fw/stlink] / example / stm32f4 / STM32_USB_Device_Library / Class / msc / src / usbd_msc_bot.c
diff --git a/example/stm32f4/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c b/example/stm32f4/STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c
new file mode 100644 (file)
index 0000000..01c88dd
--- /dev/null
@@ -0,0 +1,393 @@
+/**
+  ******************************************************************************
+  * @file    usbd_msc_bot.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    22-July-2011
+  * @brief   This file provides all the BOT protocol core functions.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "usbd_msc_bot.h"
+#include "usbd_msc_scsi.h"
+#include "usbd_ioreq.h"
+#include "usbd_msc_mem.h"
+/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
+  * @{
+  */
+
+
+/** @defgroup MSC_BOT 
+  * @brief BOT protocol module
+  * @{
+  */ 
+
+/** @defgroup MSC_BOT_Private_TypesDefinitions
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup MSC_BOT_Private_Defines
+  * @{
+  */ 
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup MSC_BOT_Private_Macros
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup MSC_BOT_Private_Variables
+  * @{
+  */ 
+uint16_t             MSC_BOT_DataLen;
+uint8_t              MSC_BOT_State;
+uint8_t              MSC_BOT_Status;
+
+#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              MSC_BOT_Data[MSC_MEDIA_PACKET] __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 MSC_BOT_CBW_TypeDef  MSC_BOT_cbw __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 MSC_BOT_CSW_TypeDef  MSC_BOT_csw __ALIGN_END ;
+/**
+  * @}
+  */ 
+
+
+/** @defgroup MSC_BOT_Private_FunctionPrototypes
+  * @{
+  */ 
+static void MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE  *pdev);
+
+static void MSC_BOT_SendData (USB_OTG_CORE_HANDLE  *pdev, 
+                              uint8_t* pbuf, 
+                              uint16_t len);
+
+static void MSC_BOT_Abort(USB_OTG_CORE_HANDLE  *pdev);
+/**
+  * @}
+  */ 
+
+
+/** @defgroup MSC_BOT_Private_Functions
+  * @{
+  */ 
+
+
+
+/**
+* @brief  MSC_BOT_Init
+*         Initialize the BOT Process
+* @param  pdev: device instance
+* @retval None
+*/
+void MSC_BOT_Init (USB_OTG_CORE_HANDLE  *pdev)
+{
+  MSC_BOT_State = BOT_IDLE;
+  MSC_BOT_Status = BOT_STATE_NORMAL;
+  USBD_STORAGE_fops->Init(0);
+  
+  DCD_EP_Flush(pdev, MSC_OUT_EP);
+  DCD_EP_Flush(pdev, MSC_IN_EP);
+  /* Prapare EP to Receive First BOT Cmd */
+  DCD_EP_PrepareRx (pdev,
+                    MSC_OUT_EP,
+                    (uint8_t *)&MSC_BOT_cbw,
+                    BOT_CBW_LENGTH);    
+}
+
+/**
+* @brief  MSC_BOT_Reset
+*         Reset the BOT Machine
+* @param  pdev: device instance
+* @retval  None
+*/
+void MSC_BOT_Reset (USB_OTG_CORE_HANDLE  *pdev)
+{
+  MSC_BOT_State = BOT_IDLE;
+  MSC_BOT_Status = BOT_STATE_RECOVERY;
+  /* Prapare EP to Receive First BOT Cmd */
+  DCD_EP_PrepareRx (pdev,
+                    MSC_OUT_EP,
+                    (uint8_t *)&MSC_BOT_cbw,
+                    BOT_CBW_LENGTH);    
+}
+
+/**
+* @brief  MSC_BOT_DeInit
+*         Uninitialize the BOT Machine
+* @param  pdev: device instance
+* @retval None
+*/
+void MSC_BOT_DeInit (USB_OTG_CORE_HANDLE  *pdev)
+{
+  MSC_BOT_State = BOT_IDLE;
+}
+
+/**
+* @brief  MSC_BOT_DataIn
+*         Handle BOT IN data stage
+* @param  pdev: device instance
+* @param  epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataIn (USB_OTG_CORE_HANDLE  *pdev, 
+                     uint8_t epnum)
+{
+  
+  switch (MSC_BOT_State)
+  {
+  case BOT_DATA_IN:
+    if(SCSI_ProcessCmd(pdev,
+                        MSC_BOT_cbw.bLUN,
+                        &MSC_BOT_cbw.CB[0]) < 0)
+    {
+      MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
+    }
+    break;
+    
+  case BOT_SEND_DATA:
+  case BOT_LAST_DATA_IN:
+    MSC_BOT_SendCSW (pdev, CSW_CMD_PASSED);
+    
+    break;
+    
+  default:
+    break;
+  }
+}
+/**
+* @brief  MSC_BOT_DataOut
+*         Proccess MSC OUT data
+* @param  pdev: device instance
+* @param  epnum: endpoint index
+* @retval None
+*/
+void MSC_BOT_DataOut (USB_OTG_CORE_HANDLE  *pdev, 
+                      uint8_t epnum)
+{
+  switch (MSC_BOT_State)
+  {
+  case BOT_IDLE:
+    MSC_BOT_CBW_Decode(pdev);
+    break;
+    
+  case BOT_DATA_OUT:
+    
+    if(SCSI_ProcessCmd(pdev,
+                        MSC_BOT_cbw.bLUN,
+                        &MSC_BOT_cbw.CB[0]) < 0)
+    {
+      MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
+    }
+
+    break;
+    
+  default:
+    break;
+  }
+  
+}
+
+/**
+* @brief  MSC_BOT_CBW_Decode
+*         Decode the CBW command and set the BOT state machine accordingtly  
+* @param  pdev: device instance
+* @retval None
+*/
+static void  MSC_BOT_CBW_Decode (USB_OTG_CORE_HANDLE  *pdev)
+{
+
+  MSC_BOT_csw.dTag = MSC_BOT_cbw.dTag;
+  MSC_BOT_csw.dDataResidue = MSC_BOT_cbw.dDataLength;
+  
+  if ((USBD_GetRxCount (pdev ,MSC_OUT_EP) != BOT_CBW_LENGTH) ||
+      (MSC_BOT_cbw.dSignature != BOT_CBW_SIGNATURE)||
+        (MSC_BOT_cbw.bLUN > 1) || 
+          (MSC_BOT_cbw.bCBLength < 1) || 
+            (MSC_BOT_cbw.bCBLength > 16))
+  {
+    
+    SCSI_SenseCode(MSC_BOT_cbw.bLUN, 
+                   ILLEGAL_REQUEST, 
+                   INVALID_CDB);
+     MSC_BOT_Status = BOT_STATE_ERROR;   
+    MSC_BOT_Abort(pdev);
+  }
+  else
+  {
+    if(SCSI_ProcessCmd(pdev,
+                              MSC_BOT_cbw.bLUN,
+                              &MSC_BOT_cbw.CB[0]) < 0)
+    {
+      MSC_BOT_Abort(pdev);
+    }
+    /*Burst xfer handled internally*/
+    else if ((MSC_BOT_State != BOT_DATA_IN) && 
+             (MSC_BOT_State != BOT_DATA_OUT) &&
+             (MSC_BOT_State != BOT_LAST_DATA_IN)) 
+    {
+      if (MSC_BOT_DataLen > 0)
+      {
+        MSC_BOT_SendData(pdev,
+                         MSC_BOT_Data, 
+                         MSC_BOT_DataLen);
+      }
+      else if (MSC_BOT_DataLen == 0) 
+      {
+        MSC_BOT_SendCSW (pdev,
+                         CSW_CMD_PASSED);
+      }
+    }
+  }
+}
+
+/**
+* @brief  MSC_BOT_SendData
+*         Send the requested data
+* @param  pdev: device instance
+* @param  buf: pointer to data buffer
+* @param  len: Data Length
+* @retval None
+*/
+static void  MSC_BOT_SendData(USB_OTG_CORE_HANDLE  *pdev,
+                              uint8_t* buf, 
+                              uint16_t len)
+{
+  
+  len = MIN (MSC_BOT_cbw.dDataLength, len);
+  MSC_BOT_csw.dDataResidue -= len;
+  MSC_BOT_csw.bStatus = CSW_CMD_PASSED;
+  MSC_BOT_State = BOT_SEND_DATA;
+  
+  DCD_EP_Tx (pdev, MSC_IN_EP, buf, len);  
+}
+
+/**
+* @brief  MSC_BOT_SendCSW
+*         Send the Command Status Wrapper
+* @param  pdev: device instance
+* @param  status : CSW status
+* @retval None
+*/
+void  MSC_BOT_SendCSW (USB_OTG_CORE_HANDLE  *pdev,
+                              uint8_t CSW_Status)
+{
+  MSC_BOT_csw.dSignature = BOT_CSW_SIGNATURE;
+  MSC_BOT_csw.bStatus = CSW_Status;
+  MSC_BOT_State = BOT_IDLE;
+  
+  DCD_EP_Tx (pdev, 
+             MSC_IN_EP, 
+             (uint8_t *)&MSC_BOT_csw, 
+             BOT_CSW_LENGTH);
+  
+  /* Prapare EP to Receive next Cmd */
+  DCD_EP_PrepareRx (pdev,
+                    MSC_OUT_EP,
+                    (uint8_t *)&MSC_BOT_cbw, 
+                    BOT_CBW_LENGTH);  
+  
+}
+
+/**
+* @brief  MSC_BOT_Abort
+*         Abort the current transfer
+* @param  pdev: device instance
+* @retval status
+*/
+
+static void  MSC_BOT_Abort (USB_OTG_CORE_HANDLE  *pdev)
+{
+
+  if ((MSC_BOT_cbw.bmFlags == 0) && 
+      (MSC_BOT_cbw.dDataLength != 0) &&
+      (MSC_BOT_Status == BOT_STATE_NORMAL) )
+  {
+    DCD_EP_Stall(pdev, MSC_OUT_EP );
+  }
+  DCD_EP_Stall(pdev, MSC_IN_EP);
+  
+  if(MSC_BOT_Status == BOT_STATE_ERROR)
+  {
+    DCD_EP_PrepareRx (pdev,
+                      MSC_OUT_EP,
+                      (uint8_t *)&MSC_BOT_cbw, 
+                      BOT_CBW_LENGTH);    
+  }
+}
+
+/**
+* @brief  MSC_BOT_CplClrFeature
+*         Complete the clear feature request
+* @param  pdev: device instance
+* @param  epnum: endpoint index
+* @retval None
+*/
+
+void  MSC_BOT_CplClrFeature (USB_OTG_CORE_HANDLE  *pdev, uint8_t epnum)
+{
+  if(MSC_BOT_Status == BOT_STATE_ERROR )/* Bad CBW Signature */
+  {
+    DCD_EP_Stall(pdev, MSC_IN_EP);
+    MSC_BOT_Status = BOT_STATE_NORMAL;    
+  }
+  else if(((epnum & 0x80) == 0x80) && ( MSC_BOT_Status != BOT_STATE_RECOVERY))
+  {
+    MSC_BOT_SendCSW (pdev, CSW_CMD_FAILED);
+  }
+  
+}
+/**
+  * @}
+  */ 
+
+
+/**
+  * @}
+  */ 
+
+
+/**
+  * @}
+  */ 
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/