/** ****************************************************************************** * @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 * *

© COPYRIGHT 2012 STMicroelectronics

* * 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****/