diff options
Diffstat (limited to 'STM32_bootloader/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c')
-rw-r--r-- | STM32_bootloader/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c | 716 |
1 files changed, 716 insertions, 0 deletions
diff --git a/STM32_bootloader/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c b/STM32_bootloader/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c new file mode 100644 index 0000000..78032c7 --- /dev/null +++ b/STM32_bootloader/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c @@ -0,0 +1,716 @@ +/** + ****************************************************************************** + * @file usbd_msc_scsi.c + * @author MCD Application Team + * @brief This file provides all the USBD SCSI layer functions. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright (c) 2015 STMicroelectronics. + * All rights reserved.</center></h2> + * + * This software component is licensed by ST under Ultimate Liberty license + * SLA0044, the "License"; You may not use this file except in compliance with + * the License. You may obtain a copy of the License at: + * www.st.com/SLA0044 + * + ****************************************************************************** + */ + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_sd.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_msc_bot.h" +#include "usbd_msc_scsi.h" +#include "usbd_msc.h" +#include "usbd_msc_data.h" + + + +/** @addtogroup STM32_USB_DEVICE_LIBRARY + * @{ + */ + + +/** @defgroup MSC_SCSI + * @brief Mass storage SCSI layer module + * @{ + */ + +/** @defgroup MSC_SCSI_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Defines + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Macros + * @{ + */ +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Variables + * @{ + */ + +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_FunctionPrototypes + * @{ + */ +static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params); +static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t blk_offset, uint32_t blk_nbr); + +static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun); +static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun); +/** + * @} + */ + + +/** @defgroup MSC_SCSI_Private_Functions + * @{ + */ + + +/** +* @brief SCSI_ProcessCmd +* Process SCSI commands +* @param pdev: device instance +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd) +{ + switch (cmd[0]) + { + case SCSI_TEST_UNIT_READY: + SCSI_TestUnitReady(pdev, lun, cmd); + break; + + case SCSI_REQUEST_SENSE: + SCSI_RequestSense(pdev, lun, cmd); + break; + case SCSI_INQUIRY: + SCSI_Inquiry(pdev, lun, cmd); + break; + + case SCSI_START_STOP_UNIT: + SCSI_StartStopUnit(pdev, lun, cmd); + break; + + case SCSI_ALLOW_MEDIUM_REMOVAL: + SCSI_StartStopUnit(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE6: + SCSI_ModeSense6(pdev, lun, cmd); + break; + + case SCSI_MODE_SENSE10: + SCSI_ModeSense10(pdev, lun, cmd); + break; + + case SCSI_READ_FORMAT_CAPACITIES: + SCSI_ReadFormatCapacity(pdev, lun, cmd); + break; + + case SCSI_READ_CAPACITY10: + SCSI_ReadCapacity10(pdev, lun, cmd); + break; + + case SCSI_READ10: + SCSI_Read10(pdev, lun, cmd); + break; + + case SCSI_WRITE10: + SCSI_Write10(pdev, lun, cmd); + break; + + case SCSI_VERIFY10: + SCSI_Verify10(pdev, lun, cmd); + break; + + default: + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + return 0; +} + + +/** +* @brief SCSI_TestUnitReady +* Process SCSI Test Unit Ready Command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_TestUnitReady(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + /* case 9 : Hi > D0 */ + if (hmsc->cbw.dDataLength != 0U) + { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + + return -1; + } + + if (((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + hmsc->bot_state = USBD_BOT_NO_DATA; + + return -1; + } + hmsc->bot_data_length = 0U; + + return 0; +} + +/** +* @brief SCSI_Inquiry +* Process Inquiry command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Inquiry(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint8_t *pPage; + uint16_t len; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + if (params[1] & 0x01U)/*Evpd is set*/ + { + len = LENGTH_INQUIRY_PAGE00; + hmsc->bot_data_length = len; + + while (len) + { + len--; + hmsc->bot_data[len] = MSC_Page00_Inquiry_Data[len]; + } + } + else + { + pPage = (uint8_t *)(void *) & ((USBD_StorageTypeDef *)pdev->pUserData)->pInquiry[lun * STANDARD_INQUIRY_DATA_LEN]; + len = (uint16_t)pPage[4] + 5U; + + if (params[4] <= len) + { + len = params[4]; + } + hmsc->bot_data_length = len; + + while (len) + { + len--; + hmsc->bot_data[len] = pPage[len]; + } + } + + return 0; +} + +/** +* @brief SCSI_ReadCapacity10 +* Process Read Capacity 10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + if (((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &hmsc->scsi_blk_nbr, &hmsc->scsi_blk_size) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + else + { + + hmsc->bot_data[0] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 24); + hmsc->bot_data[1] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 16); + hmsc->bot_data[2] = (uint8_t)((hmsc->scsi_blk_nbr - 1U) >> 8); + hmsc->bot_data[3] = (uint8_t)(hmsc->scsi_blk_nbr - 1U); + + hmsc->bot_data[4] = (uint8_t)(hmsc->scsi_blk_size >> 24); + hmsc->bot_data[5] = (uint8_t)(hmsc->scsi_blk_size >> 16); + hmsc->bot_data[6] = (uint8_t)(hmsc->scsi_blk_size >> 8); + hmsc->bot_data[7] = (uint8_t)(hmsc->scsi_blk_size); + + hmsc->bot_data_length = 8U; + return 0; + } +} +/** +* @brief SCSI_ReadFormatCapacity +* Process Read Format Capacity command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + uint16_t blk_size; + uint32_t blk_nbr; + uint16_t i; + + for (i = 0U; i < 12U ; i++) + { + hmsc->bot_data[i] = 0U; + } + + if (((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blk_nbr, &blk_size) != 0U) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + else + { + hmsc->bot_data[3] = 0x08U; + hmsc->bot_data[4] = (uint8_t)((blk_nbr - 1U) >> 24); + hmsc->bot_data[5] = (uint8_t)((blk_nbr - 1U) >> 16); + hmsc->bot_data[6] = (uint8_t)((blk_nbr - 1U) >> 8); + hmsc->bot_data[7] = (uint8_t)(blk_nbr - 1U); + + hmsc->bot_data[8] = 0x02U; + hmsc->bot_data[9] = (uint8_t)(blk_size >> 16); + hmsc->bot_data[10] = (uint8_t)(blk_size >> 8); + hmsc->bot_data[11] = (uint8_t)(blk_size); + + hmsc->bot_data_length = 12U; + return 0; + } +} +/** +* @brief SCSI_ModeSense6 +* Process Mode Sense6 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense6(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + uint16_t len = 8U; + hmsc->bot_data_length = len; + + while (len) + { + len--; + hmsc->bot_data[len] = MSC_Mode_Sense6_data[len]; + } + return 0; +} + +/** +* @brief SCSI_ModeSense10 +* Process Mode Sense10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_ModeSense10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint16_t len = 8U; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + hmsc->bot_data_length = len; + + while (len) + { + len--; + hmsc->bot_data[len] = MSC_Mode_Sense10_data[len]; + } + + return 0; +} + +/** +* @brief SCSI_RequestSense +* Process Request Sense command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_RequestSense(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + uint8_t i; + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + for (i = 0U ; i < REQUEST_SENSE_DATA_LEN; i++) + { + hmsc->bot_data[i] = 0U; + } + + hmsc->bot_data[0] = 0x70U; + hmsc->bot_data[7] = REQUEST_SENSE_DATA_LEN - 6U; + + if ((hmsc->scsi_sense_head != hmsc->scsi_sense_tail)) + { + + hmsc->bot_data[2] = hmsc->scsi_sense[hmsc->scsi_sense_head].Skey; + hmsc->bot_data[12] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASCQ; + hmsc->bot_data[13] = hmsc->scsi_sense[hmsc->scsi_sense_head].w.b.ASC; + hmsc->scsi_sense_head++; + + if (hmsc->scsi_sense_head == SENSE_LIST_DEEPTH) + { + hmsc->scsi_sense_head = 0U; + } + } + hmsc->bot_data_length = REQUEST_SENSE_DATA_LEN; + + if (params[4] <= REQUEST_SENSE_DATA_LEN) + { + hmsc->bot_data_length = params[4]; + } + return 0; +} + +/** +* @brief SCSI_SenseCode +* Load the last error code in the error list +* @param lun: Logical unit number +* @param sKey: Sense Key +* @param ASC: Additional Sense Key +* @retval none + +*/ +void SCSI_SenseCode(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t sKey, uint8_t ASC) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + + hmsc->scsi_sense[hmsc->scsi_sense_tail].Skey = sKey; + hmsc->scsi_sense[hmsc->scsi_sense_tail].w.ASC = ASC << 8; + hmsc->scsi_sense_tail++; + if (hmsc->scsi_sense_tail == SENSE_LIST_DEEPTH) + { + hmsc->scsi_sense_tail = 0U; + } +} +/** +* @brief SCSI_StartStopUnit +* Process Start Stop Unit command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + hmsc->bot_data_length = 0U; + return 0; +} + +/** +* @brief SCSI_Read10 +* Process Read10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ +static int8_t SCSI_Read10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + + if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ + { + /* case 10 : Ho <> Di */ + if ((hmsc->cbw.bmFlags & 0x80U) != 0x80U) + { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + if (((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | + ((uint32_t)params[3] << 16) | + ((uint32_t)params[4] << 8) | + (uint32_t)params[5]; + + hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | (uint32_t)params[8]; + + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) + { + return -1; /* error */ + } + + hmsc->bot_state = USBD_BOT_DATA_IN; + + /* cases 4,5 : Hi <> Dn */ + if (hmsc->cbw.dDataLength != (hmsc->scsi_blk_len * hmsc->scsi_blk_size)) + { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + } + hmsc->bot_data_length = MSC_MEDIA_PACKET; + + return SCSI_ProcessRead(pdev, lun); +} + +/** +* @brief SCSI_Write10 +* Process Write10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + uint32_t len; + + if (hmsc->bot_state == USBD_BOT_IDLE) /* Idle */ + { + /* case 8 : Hi <> Do */ + if ((hmsc->cbw.bmFlags & 0x80U) == 0x80U) + { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + /* Check whether Media is ready */ + if (((USBD_StorageTypeDef *)pdev->pUserData)->IsReady(lun) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, MEDIUM_NOT_PRESENT); + return -1; + } + + /* Check If media is write-protected */ + if (((USBD_StorageTypeDef *)pdev->pUserData)->IsWriteProtected(lun) != 0) + { + SCSI_SenseCode(pdev, lun, NOT_READY, WRITE_PROTECTED); + return -1; + } + + hmsc->scsi_blk_addr = ((uint32_t)params[2] << 24) | + ((uint32_t)params[3] << 16) | + ((uint32_t)params[4] << 8) | + (uint32_t)params[5]; + + hmsc->scsi_blk_len = ((uint32_t)params[7] << 8) | + (uint32_t)params[8]; + + /* check if LBA address is in the right range */ + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) + { + return -1; /* error */ + } + + len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + /* cases 3,11,13 : Hn,Ho <> D0 */ + if (hmsc->cbw.dDataLength != len) + { + SCSI_SenseCode(pdev, hmsc->cbw.bLUN, ILLEGAL_REQUEST, INVALID_CDB); + return -1; + } + + len = MIN(len, MSC_MEDIA_PACKET); + + /* Prepare EP to receive first data packet */ + hmsc->bot_state = USBD_BOT_DATA_OUT; + USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } + else /* Write Process ongoing */ + { + return SCSI_ProcessWrite(pdev, lun); + } + return 0; +} + + +/** +* @brief SCSI_Verify10 +* Process Verify10 command +* @param lun: Logical unit number +* @param params: Command parameters +* @retval status +*/ + +static int8_t SCSI_Verify10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + + if ((params[1] & 0x02U) == 0x02U) + { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + return -1; /* Error, Verify Mode Not supported*/ + } + + if (SCSI_CheckAddressRange(pdev, lun, hmsc->scsi_blk_addr, + hmsc->scsi_blk_len) < 0) + { + return -1; /* error */ + } + hmsc->bot_data_length = 0U; + return 0; +} + +/** +* @brief SCSI_CheckAddressRange +* Check address range +* @param lun: Logical unit number +* @param blk_offset: first block address +* @param blk_nbr: number of block to be processed +* @retval status +*/ +static int8_t SCSI_CheckAddressRange(USBD_HandleTypeDef *pdev, uint8_t lun, + uint32_t blk_offset, uint32_t blk_nbr) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + + if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr) + { + SCSI_SenseCode(pdev, lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + return -1; + } + return 0; +} + +/** +* @brief SCSI_ProcessRead +* Handle Read Process +* @param lun: Logical unit number +* @retval status +*/ +static int8_t SCSI_ProcessRead(USBD_HandleTypeDef *pdev, uint8_t lun) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *)pdev->pClassData; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (((USBD_StorageTypeDef *)pdev->pUserData)->Read(lun, + hmsc->bot_data, + hmsc->scsi_blk_addr, + (len / hmsc->scsi_blk_size)) < 0) + { + SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, UNRECOVERED_READ_ERROR); + return -1; + } + + USBD_LL_Transmit(pdev, MSC_EPIN_ADDR, hmsc->bot_data, len); + + hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size); + hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size); + + /* case 6 : Hi = Di */ + hmsc->csw.dDataResidue -= len; + + if (hmsc->scsi_blk_len == 0U) + { + hmsc->bot_state = USBD_BOT_LAST_DATA_IN; + } + return 0; +} + +/** +* @brief SCSI_ProcessWrite +* Handle Write Process +* @param lun: Logical unit number +* @retval status +*/ + +static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun) +{ + USBD_MSC_BOT_HandleTypeDef *hmsc = (USBD_MSC_BOT_HandleTypeDef *) pdev->pClassData; + uint32_t len = hmsc->scsi_blk_len * hmsc->scsi_blk_size; + + len = MIN(len, MSC_MEDIA_PACKET); + + if (((USBD_StorageTypeDef *)pdev->pUserData)->Write(lun, hmsc->bot_data, + hmsc->scsi_blk_addr, + (len / hmsc->scsi_blk_size)) < 0) + { + SCSI_SenseCode(pdev, lun, HARDWARE_ERROR, WRITE_FAULT); + + return -1; + } + + hmsc->scsi_blk_addr += (len / hmsc->scsi_blk_size); + hmsc->scsi_blk_len -= (len / hmsc->scsi_blk_size); + + /* case 12 : Ho = Do */ + hmsc->csw.dDataResidue -= len; + + if (hmsc->scsi_blk_len == 0U) + { + MSC_BOT_SendCSW(pdev, USBD_CSW_CMD_PASSED); + } + else + { + len = MIN((hmsc->scsi_blk_len * hmsc->scsi_blk_size), MSC_MEDIA_PACKET); + /* Prepare EP to Receive next packet */ + USBD_LL_PrepareReceive(pdev, MSC_EPOUT_ADDR, hmsc->bot_data, len); + } + + return 0; +} +/** + * @} + */ + + +/** + * @} + */ + + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |