diff options
Diffstat (limited to 'thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Projects/Composite_Example/src/usb_bot.c')
-rw-r--r-- | thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Projects/Composite_Example/src/usb_bot.c | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Projects/Composite_Example/src/usb_bot.c b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Projects/Composite_Example/src/usb_bot.c new file mode 100644 index 0000000..5773bac --- /dev/null +++ b/thirdparty/STM32_USB-FS-Device_Lib_V4.0.0/Projects/Composite_Example/src/usb_bot.c @@ -0,0 +1,343 @@ +/** + ****************************************************************************** + * @file usb_bot.c + * @author MCD Application Team + * @version V4.0.0 + * @date 21-January-2013 + * @brief BOT State Machine management + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT 2013 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 "usb_scsi.h" +#include "hw_config.h" +#include "usb_regs.h" +#include "usb_mem.h" +#include "usb_conf.h" +#include "usb_bot.h" +#include "memory.h" +#include "usb_lib.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +uint8_t Bot_State; +uint8_t Bulk_Data_Buff[64]; /* data buffer*/ +uint16_t Data_Len; +Bulk_Only_CBW CBW; +Bulk_Only_CSW CSW; +uint32_t SCSI_LBA , SCSI_BlkLen; +extern uint32_t Max_Lun; +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Extern function prototypes ------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : Mass_Storage_In +* Description : Mass Storage IN transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void Mass_Storage_In (void) +{ + switch (Bot_State) + { + case BOT_CSW_Send: + case BOT_ERROR: + Bot_State = BOT_IDLE; + SetEPRxStatus(ENDP2, EP_RX_VALID);/* enable the Endpoint to receive the next cmd*/ + if (GetEPRxStatus(EP2_OUT) == EP_RX_STALL) + { + SetEPRxStatus(EP2_OUT, EP_RX_VALID);/* enable the Endpoint to receive the next cmd*/ + } + break; + case BOT_DATA_IN: + switch (CBW.CB[0]) + { + case SCSI_READ10: + SCSI_Read10_Cmd(CBW.bLUN , SCSI_LBA , SCSI_BlkLen); + break; + } + break; + case BOT_DATA_IN_LAST: + Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + + SetEPRxStatus(ENDP2, EP_RX_VALID); + break; + default: + break; + } +} + +/******************************************************************************* +* Function Name : Mass_Storage_Out +* Description : Mass Storage OUT transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void Mass_Storage_Out (void) +{ + uint8_t CMD; + CMD = CBW.CB[0]; + + Data_Len = USB_SIL_Read(EP2_OUT, Bulk_Data_Buff); + + switch (Bot_State) + { + case BOT_IDLE: + CBW_Decode(); + break; + case BOT_DATA_OUT: + if (CMD == SCSI_WRITE10) + { + SCSI_Write10_Cmd(CBW.bLUN , SCSI_LBA , SCSI_BlkLen); + break; + } + Bot_Abort(DIR_OUT); + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + Set_CSW (CSW_PHASE_ERROR, SEND_CSW_DISABLE); + break; + default: + Bot_Abort(BOTH_DIR); + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + Set_CSW (CSW_PHASE_ERROR, SEND_CSW_DISABLE); + break; + } +} + +/******************************************************************************* +* Function Name : CBW_Decode +* Description : Decode the received CBW and call the related SCSI command +* routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void CBW_Decode(void) +{ + uint32_t Counter; + + for (Counter = 0; Counter < Data_Len; Counter++) + { + *((uint8_t *)&CBW + Counter) = Bulk_Data_Buff[Counter]; + } + CSW.dTag = CBW.dTag; + CSW.dDataResidue = CBW.dDataLength; + if (Data_Len != BOT_CBW_PACKET_LENGTH) + { + Bot_Abort(BOTH_DIR); + /* reset the CBW.dSignature to disable the clear feature until receiving a Mass storage reset*/ + CBW.dSignature = 0; + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERROR); + Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + return; + } + + if ((CBW.CB[0] == SCSI_READ10 ) || (CBW.CB[0] == SCSI_WRITE10 )) + { + /* Calculate Logical Block Address */ + SCSI_LBA = (CBW.CB[2] << 24) | (CBW.CB[3] << 16) | (CBW.CB[4] << 8) | CBW.CB[5]; + /* Calculate the Number of Blocks to transfer */ + SCSI_BlkLen = (CBW.CB[7] << 8) | CBW.CB[8]; + } + + if (CBW.dSignature == BOT_CBW_SIGNATURE) + { + /* Valid CBW */ + if ((CBW.bLUN > Max_Lun) || (CBW.bCBLength < 1) || (CBW.bCBLength > 16)) + { + Bot_Abort(BOTH_DIR); + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + else + { + switch (CBW.CB[0]) + { + case SCSI_REQUEST_SENSE: + SCSI_RequestSense_Cmd (CBW.bLUN); + break; + case SCSI_INQUIRY: + SCSI_Inquiry_Cmd(CBW.bLUN); + break; + case SCSI_START_STOP_UNIT: + SCSI_Start_Stop_Unit_Cmd(CBW.bLUN); + break; + case SCSI_ALLOW_MEDIUM_REMOVAL: + SCSI_Start_Stop_Unit_Cmd(CBW.bLUN); + break; + case SCSI_MODE_SENSE6: + SCSI_ModeSense6_Cmd (CBW.bLUN); + break; + case SCSI_MODE_SENSE10: + SCSI_ModeSense10_Cmd (CBW.bLUN); + break; + case SCSI_READ_FORMAT_CAPACITIES: + SCSI_ReadFormatCapacity_Cmd(CBW.bLUN); + break; + case SCSI_READ_CAPACITY10: + SCSI_ReadCapacity10_Cmd(CBW.bLUN); + break; + case SCSI_TEST_UNIT_READY: + SCSI_TestUnitReady_Cmd(CBW.bLUN); + break; + case SCSI_READ10: + SCSI_Read10_Cmd(CBW.bLUN, SCSI_LBA , SCSI_BlkLen); + break; + case SCSI_WRITE10: + SCSI_Write10_Cmd(CBW.bLUN, SCSI_LBA , SCSI_BlkLen); + break; + case SCSI_VERIFY10: + SCSI_Verify10_Cmd(CBW.bLUN); + break; + case SCSI_FORMAT_UNIT: + SCSI_Format_Cmd(CBW.bLUN); + break; + /*Unsupported command*/ + case SCSI_MODE_SELECT10: + SCSI_Mode_Select10_Cmd(CBW.bLUN); + break; + case SCSI_MODE_SELECT6: + SCSI_Mode_Select6_Cmd(CBW.bLUN); + break; + + case SCSI_SEND_DIAGNOSTIC: + SCSI_Send_Diagnostic_Cmd(CBW.bLUN); + break; + case SCSI_READ6: + SCSI_Read6_Cmd(CBW.bLUN); + break; + case SCSI_READ12: + SCSI_Read12_Cmd(CBW.bLUN); + break; + case SCSI_READ16: + SCSI_Read16_Cmd(CBW.bLUN); + break; + case SCSI_READ_CAPACITY16: + SCSI_READ_CAPACITY16_Cmd(CBW.bLUN); + break; + case SCSI_WRITE6: + SCSI_Write6_Cmd(CBW.bLUN); + break; + case SCSI_WRITE12: + SCSI_Write12_Cmd(CBW.bLUN); + break; + case SCSI_WRITE16: + SCSI_Write16_Cmd(CBW.bLUN); + break; + case SCSI_VERIFY12: + SCSI_Verify12_Cmd(CBW.bLUN); + break; + case SCSI_VERIFY16: + SCSI_Verify16_Cmd(CBW.bLUN); + break; + + default: + { + Bot_Abort(BOTH_DIR); + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + } + } + } + else + { + /* Invalid CBW */ + Bot_Abort(BOTH_DIR); + Set_Scsi_Sense_Data(CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } +} + +/******************************************************************************* +* Function Name : Transfer_Data_Request +* Description : Send the request response to the PC HOST. +* Input : uint8_t* Data_Address : point to the data to transfer. +* uint16_t Data_Length : the number of Bytes to transfer. +* Output : None. +* Return : None. +*******************************************************************************/ +void Transfer_Data_Request(uint8_t* Data_Pointer, uint16_t Data_Len) +{ + USB_SIL_Write(EP2_IN, Data_Pointer, Data_Len); + + SetEPTxStatus(ENDP2, EP_TX_VALID); + + Bot_State = BOT_DATA_IN_LAST; + CSW.dDataResidue -= Data_Len; + CSW.bStatus = CSW_CMD_PASSED; +} + +/******************************************************************************* +* Function Name : Set_CSW +* Description : Set the SCW with the needed fields. +* Input : uint8_t CSW_Status this filed can be CSW_CMD_PASSED,CSW_CMD_FAILED, +* or CSW_PHASE_ERROR. +* Output : None. +* Return : None. +*******************************************************************************/ +void Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission) +{ + CSW.dSignature = BOT_CSW_SIGNATURE; + CSW.bStatus = CSW_Status; + + USB_SIL_Write(EP2_IN, ((uint8_t *)& CSW), CSW_DATA_LENGTH); + + Bot_State = BOT_ERROR; + if (Send_Permission) + { + Bot_State = BOT_CSW_Send; + SetEPTxStatus(ENDP2, EP_TX_VALID); + } +} + +/******************************************************************************* +* Function Name : Bot_Abort +* Description : Stall the needed Endpoint according to the selected direction. +* Input : Endpoint direction IN, OUT or both directions +* Output : None. +* Return : None. +*******************************************************************************/ +void Bot_Abort(uint8_t Direction) +{ + switch (Direction) + { + case DIR_IN : + SetEPTxStatus(ENDP2, EP_TX_STALL); + break; + case DIR_OUT : + SetEPRxStatus(ENDP2, EP_RX_STALL); + break; + case BOTH_DIR : + SetEPTxStatus(ENDP2, EP_TX_STALL); + SetEPRxStatus(ENDP2, EP_RX_STALL); + break; + default: + break; + } +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |