X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=example%2Fstm32f4%2FSTM32_USB_HOST_Library%2FClass%2FMSC%2Fsrc%2Fusbh_msc_bot.c;fp=example%2Fstm32f4%2FSTM32_USB_HOST_Library%2FClass%2FMSC%2Fsrc%2Fusbh_msc_bot.c;h=eeb10755b8f8625185cec05b49e700252c9568c7;hb=83a5eb2ed34ed78edacd92a69f366b89728ac5d0;hp=0000000000000000000000000000000000000000;hpb=794a560ebf95fcc97a56b89827d273cf0f726c87;p=fw%2Fstlink diff --git a/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c new file mode 100644 index 0000000..eeb1075 --- /dev/null +++ b/example/stm32f4/STM32_USB_HOST_Library/Class/MSC/src/usbh_msc_bot.c @@ -0,0 +1,613 @@ +/** + ****************************************************************************** + * @file usbh_msc_bot.c + * @author MCD Application Team + * @version V2.0.0 + * @date 22-July-2011 + * @brief This file includes the mass storage related 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. + * + *

© COPYRIGHT 2011 STMicroelectronics

+ ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_msc_core.h" +#include "usbh_msc_scsi.h" +#include "usbh_msc_bot.h" +#include "usbh_ioreq.h" +#include "usbh_def.h" +#include "usb_hcd_int.h" + + +/** @addtogroup USBH_LIB +* @{ +*/ + +/** @addtogroup USBH_CLASS +* @{ +*/ + +/** @addtogroup USBH_MSC_CLASS +* @{ +*/ + +/** @defgroup USBH_MSC_BOT +* @brief This file includes the mass storage related functions +* @{ +*/ + + +/** @defgroup USBH_MSC_BOT_Private_TypesDefinitions +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_MSC_BOT_Private_Defines +* @{ +*/ +/** +* @} +*/ + +/** @defgroup USBH_MSC_BOT_Private_Macros +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_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 HostCBWPkt_TypeDef USBH_MSC_CBWData __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 HostCSWPkt_TypeDef USBH_MSC_CSWData __ALIGN_END ; + + +static uint32_t BOTStallErrorCount; /* Keeps count of STALL Error Cases*/ + +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes +* @{ +*/ +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Exported_Variables +* @{ +*/ +USBH_BOTXfer_TypeDef USBH_MSC_BOTXferParam; +/** +* @} +*/ + + +/** @defgroup USBH_MSC_BOT_Private_Functions +* @{ +*/ + + +/** +* @brief USBH_MSC_Init +* Initializes the mass storage parameters +* @param None +* @retval None +*/ +void USBH_MSC_Init(USB_OTG_CORE_HANDLE *pdev ) +{ + if(HCD_IsDeviceConnected(pdev)) + { + USBH_MSC_CBWData.field.CBWSignature = USBH_MSC_BOT_CBW_SIGNATURE; + USBH_MSC_CBWData.field.CBWTag = USBH_MSC_BOT_CBW_TAG; + USBH_MSC_CBWData.field.CBWLUN = 0; /*Only one LUN is supported*/ + USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE; + } + + BOTStallErrorCount = 0; + MSCErrorCount = 0; +} + +/** +* @brief USBH_MSC_HandleBOTXfer +* This function manages the different states of BOT transfer and +* updates the status to upper layer. +* @param None +* @retval None +* +*/ +void USBH_MSC_HandleBOTXfer (USB_OTG_CORE_HANDLE *pdev ,USBH_HOST *phost) +{ + uint8_t xferDirection, index; + static uint32_t remainingDataLength; + static uint8_t *datapointer; + static uint8_t error_direction; + USBH_Status status; + + URB_STATE URB_Status = URB_IDLE; + + if(HCD_IsDeviceConnected(pdev)) + { + + switch (USBH_MSC_BOTXferParam.BOTState) + { + case USBH_MSC_SEND_CBW: + /* send CBW */ + USBH_BulkSendData (pdev, + &USBH_MSC_CBWData.CBWArray[0], + USBH_MSC_BOT_CBW_PACKET_LENGTH , + MSC_Machine.hc_num_out); + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW; + + break; + + case USBH_MSC_SENT_CBW: + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out); + + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW; + + /* If the CBW Pkt is sent successful, then change the state */ + xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK); + + if ( USBH_MSC_CBWData.field.CBWTransferLength != 0 ) + { + remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength ; + datapointer = USBH_MSC_BOTXferParam.pRxTxBuff; + + /* If there is Data Transfer Stage */ + if (xferDirection == USB_D2H) + { + /* Data Direction is IN */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAIN_STATE; + } + else + { + /* Data Direction is OUT */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAOUT_STATE; + } + } + + else + {/* If there is NO Data Transfer Stage */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + + } + else if(URB_Status == URB_NOTREADY) + { + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_OUT; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; + } + break; + + case USBH_MSC_BOT_DATAIN_STATE: + + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in); + /* BOT DATA IN stage */ + if((URB_Status == URB_DONE) ||(USBH_MSC_BOTXferParam.BOTStateBkp != USBH_MSC_BOT_DATAIN_STATE)) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE; + + if(remainingDataLength > USBH_MSC_MPS_SIZE) + { + USBH_BulkReceiveData (pdev, + datapointer, + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_in); + + remainingDataLength -= USBH_MSC_MPS_SIZE; + datapointer = datapointer + USBH_MSC_MPS_SIZE; + } + else if ( remainingDataLength == 0) + { + /* If value was 0, and successful transfer, then change the state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + else + { + USBH_BulkReceiveData (pdev, + datapointer, + remainingDataLength , + MSC_Machine.hc_num_in); + + remainingDataLength = 0; /* Reset this value and keep in same state */ + } + } + else if(URB_Status == URB_STALL) + { + /* This is Data Stage STALL Condition */ + + error_direction = USBH_MSC_DIR_IN; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN; + + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + 6.7.2 Host expects to receive data from the device + 3. On a STALL condition receiving data, then: + The host shall accept the data received. + The host shall clear the Bulk-In pipe. + 4. The host shall attempt to receive a CSW. + + USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original + state after the ClearFeature Command is issued. + */ + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + } + break; + + + case USBH_MSC_BOT_DATAOUT_STATE: + /* BOT DATA OUT stage */ + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_out); + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE; + if(remainingDataLength > USBH_MSC_MPS_SIZE) + { + USBH_BulkSendData (pdev, + datapointer, + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_out); + datapointer = datapointer + USBH_MSC_MPS_SIZE; + remainingDataLength = remainingDataLength - USBH_MSC_MPS_SIZE; + } + else if ( remainingDataLength == 0) + { + /* If value was 0, and successful transfer, then change the state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; + } + else + { + USBH_BulkSendData (pdev, + datapointer, + remainingDataLength , + MSC_Machine.hc_num_out); + + remainingDataLength = 0; /* Reset this value and keep in same state */ + } + } + + else if(URB_Status == URB_NOTREADY) + { + USBH_BulkSendData (pdev, + (datapointer - USBH_MSC_MPS_SIZE), + USBH_MSC_MPS_SIZE , + MSC_Machine.hc_num_out); + } + + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_OUT; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; + + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + 6.7.3 Ho - Host expects to send data to the device + 3. On a STALL condition sending data, then: + " The host shall clear the Bulk-Out pipe. + 4. The host shall attempt to receive a CSW. + + The Above statement will do the clear the Bulk-Out pipe. + The Below statement will help in Getting the CSW. + + USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original + state after the ClearFeature Command is issued. + */ + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + } + break; + + case USBH_MSC_RECEIVE_CSW_STATE: + /* BOT CSW stage */ + /* NOTE: We cannot reset the BOTStallErrorCount here as it may come from + the clearFeature from previous command */ + + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray; + USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH; + + for(index = USBH_MSC_CSW_LENGTH; index != 0; index--) + { + USBH_MSC_CSWData.CSWArray[index] = 0; + } + + USBH_MSC_CSWData.CSWArray[0] = 0; + + USBH_BulkReceiveData (pdev, + USBH_MSC_BOTXferParam.pRxTxBuff, + USBH_MSC_CSW_MAX_LENGTH , + MSC_Machine.hc_num_in); + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW; + + break; + + case USBH_MSC_DECODE_CSW: + URB_Status = HCD_GetURB_State(pdev , MSC_Machine.hc_num_in); + /* Decode CSW */ + if(URB_Status == URB_DONE) + { + BOTStallErrorCount = 0; + USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; + + USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent ; + + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev , phost); + } + else if(URB_Status == URB_STALL) + { + error_direction = USBH_MSC_DIR_IN; + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN; + } + break; + + case USBH_MSC_BOT_ERROR_IN: + status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN); + if (status == USBH_OK) + { + /* Check if the error was due in Both the directions */ + if (error_direction == USBH_MSC_BOTH_DIR) + {/* If Both directions are Needed, Switch to OUT Direction */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; + } + else + { + /* Switch Back to the Original State, In many cases this will be + USBH_MSC_RECEIVE_CSW_STATE state */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + } + else if (status == USBH_UNRECOVERED_ERROR) + { + /* This means that there is a STALL Error limit, Do Reset Recovery */ + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; + } + break; + + case USBH_MSC_BOT_ERROR_OUT: + status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT); + if ( status == USBH_OK) + { /* Switch Back to the Original State */ + USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; + } + else if (status == USBH_UNRECOVERED_ERROR) + { + /* This means that there is a STALL Error limit, Do Reset Recovery */ + USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; + } + break; + + default: + break; + } + } +} + +/** +* @brief USBH_MSC_BOT_Abort +* This function manages the different Error handling for STALL +* @param direction : IN / OUT +* @retval None +*/ +USBH_Status USBH_MSC_BOT_Abort(USB_OTG_CORE_HANDLE *pdev, + USBH_HOST *phost, + uint8_t direction) +{ + USBH_Status status; + + status = USBH_BUSY; + + switch (direction) + { + case USBH_MSC_DIR_IN : + /* send ClrFeture on Bulk IN endpoint */ + status = USBH_ClrFeature(pdev, + phost, + MSC_Machine.MSBulkInEp, + MSC_Machine.hc_num_in); + + break; + + case USBH_MSC_DIR_OUT : + /*send ClrFeature on Bulk OUT endpoint */ + status = USBH_ClrFeature(pdev, + phost, + MSC_Machine.MSBulkOutEp, + MSC_Machine.hc_num_out); + break; + + default: + break; + } + + BOTStallErrorCount++; /* Check Continous Number of times, STALL has Occured */ + if (BOTStallErrorCount > MAX_BULK_STALL_COUNT_LIMIT ) + { + status = USBH_UNRECOVERED_ERROR; + } + + return status; +} + +/** +* @brief USBH_MSC_DecodeCSW +* This function decodes the CSW received by the device and updates the +* same to upper layer. +* @param None +* @retval On success USBH_MSC_OK, on failure USBH_MSC_FAIL +* @notes +* Refer to USB Mass-Storage Class : BOT (www.usb.org) +* 6.3.1 Valid CSW Conditions : +* The host shall consider the CSW valid when: +* 1. dCSWSignature is equal to 53425355h +* 2. the CSW is 13 (Dh) bytes in length, +* 3. dCSWTag matches the dCBWTag from the corresponding CBW. +*/ + +uint8_t USBH_MSC_DecodeCSW(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost) +{ + uint8_t status; + uint32_t dataXferCount = 0; + status = USBH_MSC_FAIL; + + if(HCD_IsDeviceConnected(pdev)) + { + /*Checking if the transfer length is diffrent than 13*/ + dataXferCount = HCD_GetXferCnt(pdev, MSC_Machine.hc_num_in); + + if(dataXferCount != USBH_MSC_CSW_LENGTH) + { + /*(4) Hi > Dn (Host expects to receive data from the device, + Device intends to transfer no data) + (5) Hi > Di (Host expects to receive data from the device, + Device intends to send data to the host) + (9) Ho > Dn (Host expects to send data to the device, + Device intends to transfer no data) + (11) Ho > Do (Host expects to send data to the device, + Device intends to receive data from the host)*/ + + + status = USBH_MSC_PHASE_ERROR; + } + else + { /* CSW length is Correct */ + + /* Check validity of the CSW Signature and CSWStatus */ + if(USBH_MSC_CSWData.field.CSWSignature == USBH_MSC_BOT_CSW_SIGNATURE) + {/* Check Condition 1. dCSWSignature is equal to 53425355h */ + + if(USBH_MSC_CSWData.field.CSWTag == USBH_MSC_CBWData.field.CBWTag) + { + /* Check Condition 3. dCSWTag matches the dCBWTag from the + corresponding CBW */ + + if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_OK) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + + Hn Host expects no data transfers + Hi Host expects to receive data from the device + Ho Host expects to send data to the device + + Dn Device intends to transfer no data + Di Device intends to send data to the host + Do Device intends to receive data from the host + + Section 6.7 + (1) Hn = Dn (Host expects no data transfers, + Device intends to transfer no data) + (6) Hi = Di (Host expects to receive data from the device, + Device intends to send data to the host) + (12) Ho = Do (Host expects to send data to the device, + Device intends to receive data from the host) + + */ + + status = USBH_MSC_OK; + } + else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_FAIL) + { + status = USBH_MSC_FAIL; + } + + else if(USBH_MSC_CSWData.field.CSWStatus == USBH_MSC_PHASE_ERROR) + { + /* Refer to USB Mass-Storage Class : BOT (www.usb.org) + Section 6.7 + (2) Hn < Di ( Host expects no data transfers, + Device intends to send data to the host) + (3) Hn < Do ( Host expects no data transfers, + Device intends to receive data from the host) + (7) Hi < Di ( Host expects to receive data from the device, + Device intends to send data to the host) + (8) Hi <> Do ( Host expects to receive data from the device, + Device intends to receive data from the host) + (10) Ho <> Di (Host expects to send data to the device, + Di Device intends to send data to the host) + (13) Ho < Do (Host expects to send data to the device, + Device intends to receive data from the host) + */ + + status = USBH_MSC_PHASE_ERROR; + } + } /* CSW Tag Matching is Checked */ + } /* CSW Signature Correct Checking */ + else + { + /* If the CSW Signature is not valid, We sall return the Phase Error to + Upper Layers for Reset Recovery */ + + status = USBH_MSC_PHASE_ERROR; + } + } /* CSW Length Check*/ + } + + USBH_MSC_BOTXferParam.BOTXferStatus = status; + return status; +} + + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/** +* @} +*/ + +/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ + + +