402 lines
9.4 KiB
C
402 lines
9.4 KiB
C
/**
|
|
******************************************************************************
|
|
* @file usbd_msc_bot.c
|
|
* @author MCD Application Team
|
|
* @version V1.1.0
|
|
* @date 19-March-2012
|
|
* @brief This file provides all the BOT protocol core functions.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* <h2><center>© 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 "usbd_msc_bot.h"
|
|
#include "usbd_msc_scsi.h"
|
|
#include "usbd_ioreq.h"
|
|
#include "usbd_msc_mem.h"
|
|
#include "usbd_conf.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 STMicroelectronics *****END OF FILE****/
|