From 0e1fed6047ae102224c3803c8cc34d50de907bf9 Mon Sep 17 00:00:00 2001 From: Robert Fisk Date: Sun, 16 Aug 2015 19:20:36 +1200 Subject: [PATCH] Full implementation of Downstream MSC interface, including significant modifications to USB host MSC. Also, minor tweaks to Upstream. --- Downstream/Inc/downstream_msc.h | 12 + Downstream/Inc/downstream_statemachine.h | 1 + .../Class/MSC/Inc/usbh_msc.h | 66 ++-- .../Class/MSC/Inc/usbh_msc_bot.h | 9 +- .../Class/MSC/Inc/usbh_msc_scsi.h | 2 - .../Class/MSC/Src/usbh_msc.c | 97 +++--- .../Class/MSC/Src/usbh_msc_bot.c | 327 +++++++++--------- .../Class/MSC/Src/usbh_msc_scsi.c | 17 +- Downstream/Src/downstream_msc.c | 187 ++++++++-- Downstream/Src/downstream_spi.c | 62 +++- Downstream/Src/downstream_statemachine.c | 1 - .../Class/MSC/Src/usbd_msc_scsi.c | 3 +- Upstream/Src/upstream_msc.c | 15 +- Upstream/Src/upstream_msc_mock.c | 2 +- Upstream/Src/upstream_spi.c | 15 +- 15 files changed, 489 insertions(+), 327 deletions(-) diff --git a/Downstream/Inc/downstream_msc.h b/Downstream/Inc/downstream_msc.h index 8b1e5b4..70f9b62 100644 --- a/Downstream/Inc/downstream_msc.h +++ b/Downstream/Inc/downstream_msc.h @@ -12,8 +12,20 @@ #include "downstream_spi.h" +#define MSC_SUPPORTED_BLOCK_SIZE 512 +#define MSC_FIXED_LUN 0 + + +typedef void (*DownstreamMSCCallbackPacketTypeDef)(HAL_StatusTypeDef result, + DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength); + + HAL_StatusTypeDef Downstream_MSC_ApproveConnectedDevice(void); void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); +HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* packetToSend, + uint32_t dataLength); +HAL_StatusTypeDef Downstream_MSC_GetStreamDataPacket(DownstreamMSCCallbackPacketTypeDef callback); diff --git a/Downstream/Inc/downstream_statemachine.h b/Downstream/Inc/downstream_statemachine.h index dc61ce4..1e9a29c 100644 --- a/Downstream/Inc/downstream_statemachine.h +++ b/Downstream/Inc/downstream_statemachine.h @@ -26,6 +26,7 @@ typedef enum void Downstream_InitStateMachine(void); void Downstream_HostUserCallback(USBH_HandleTypeDef *phost, uint8_t id); +void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_ErrorReply(DownstreamPacketTypeDef* replyPacket); void Downstream_PacketProcessor_ClassReply(DownstreamPacketTypeDef* replyPacket); diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h index 378a99c..ae07676 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc.h @@ -38,28 +38,9 @@ #include "usbh_msc_bot.h" #include "usbh_msc_scsi.h" -/** @addtogroup USBH_LIB - * @{ - */ - -/** @addtogroup USBH_CLASS - * @{ - */ - -/** @addtogroup USBH_MSC_CLASS - * @{ - */ -/** @defgroup USBH_MSC_CORE - * @brief This file is the Header file for usbh_msc.c - * @{ - */ -/** @defgroup USBH_MSC_CORE_Exported_Types - * @{ - */ - typedef enum { MSC_INIT = 0, @@ -112,25 +93,29 @@ typedef struct } MSC_LUNTypeDef; + +typedef void (*MSC_RdWrCompleteCallback)(USBH_StatusTypeDef result); + /* Structure for MSC process */ typedef struct _MSC_Process { - uint32_t max_lun; - uint8_t InPipe; - uint8_t OutPipe; - uint8_t OutEp; - uint8_t InEp; - uint16_t OutEpSize; - uint16_t InEpSize; - MSC_StateTypeDef state; - MSC_ErrorTypeDef error; - MSC_ReqStateTypeDef req_state; - MSC_ReqStateTypeDef prev_req_state; - BOT_HandleTypeDef hbot; - MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN]; - uint16_t current_lun; - uint16_t rw_lun; - uint32_t timer; + uint32_t max_lun; + uint8_t InPipe; + uint8_t OutPipe; + uint8_t OutEp; + uint8_t InEp; + uint16_t OutEpSize; + uint16_t InEpSize; + MSC_StateTypeDef state; + MSC_ErrorTypeDef error; + MSC_ReqStateTypeDef req_state; + MSC_ReqStateTypeDef prev_req_state; + BOT_HandleTypeDef hbot; + MSC_LUNTypeDef unit[MAX_SUPPORTED_LUN]; + uint16_t current_lun; + uint16_t rw_lun; + uint32_t timeout; + MSC_RdWrCompleteCallback RdWrCompleteCallback; } MSC_HandleTypeDef; @@ -147,7 +132,8 @@ MSC_HandleTypeDef; #define USB_REQ_BOT_RESET 0xFF #define USB_REQ_GET_MAX_LUN 0xFE - + +#define MSC_TIMEOUT_FRAMES_PER_BLOCK 1000 /* MSC Class Codes */ #define USB_MSC_CLASS 0x08 @@ -193,14 +179,14 @@ USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, M USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, - uint32_t length); + uint32_t length, + MSC_RdWrCompleteCallback callback); USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, - uint32_t length); + uint32_t length, + MSC_RdWrCompleteCallback callback); /** * @} */ diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h index 51c2ce9..fba8501 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_bot.h @@ -36,6 +36,8 @@ /* Includes ------------------------------------------------------------------*/ #include "usbh_core.h" #include "usbh_msc_bot.h" +#include "downstream_spi.h" + /** @addtogroup USBH_LIB * @{ @@ -137,8 +139,11 @@ typedef struct BOT_CBWTypeDef cbw; uint8_t Reserved1; BOT_CSWTypeDef csw; - uint8_t Reserved2[3]; - uint8_t *pbuf; + uint8_t Reserved2[3]; + uint8_t* pbuf; + DownstreamPacketTypeDef* bot_packet; + uint16_t bot_packet_bytes_remaining; + uint16_t this_URB_size; } BOT_HandleTypeDef; diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h index b7b2a54..e57028e 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc/usbh_msc_scsi.h @@ -185,13 +185,11 @@ USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, uint32_t length); USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, uint32_t length); diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c index 8953109..522bef6 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc.c @@ -195,6 +195,7 @@ static USBH_StatusTypeDef USBH_MSC_InterfaceInit (USBH_HandleTypeDef *phost) MSC_Handle->req_state = MSC_REQ_IDLE; MSC_Handle->OutPipe = USBH_AllocPipe(phost, MSC_Handle->OutEp); MSC_Handle->InPipe = USBH_AllocPipe(phost, MSC_Handle->InEp); + MSC_Handle->RdWrCompleteCallback = NULL; USBH_MSC_BOT_Init(phost); @@ -343,7 +344,7 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) case MSC_INIT: USBH_UsrLog ("LUN #%d: ", MSC_Handle->current_lun); MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_READ_INQUIRY; - MSC_Handle->timer = phost->Timer; + MSC_Handle->timeout = phost->Timer; case MSC_READ_INQUIRY: scsi_status = USBH_MSC_SCSI_Inquiry(phost, MSC_Handle->current_lun, &MSC_Handle->unit[MSC_Handle->current_lun].inquiry); @@ -443,7 +444,7 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) (MSC_Handle->unit[MSC_Handle->current_lun].sense.key == SCSI_SENSE_KEY_NOT_READY) ) { - if((phost->Timer - MSC_Handle->timer) > 10000) + if((phost->Timer - MSC_Handle->timeout) > 10000) { MSC_Handle->unit[MSC_Handle->current_lun].state = MSC_TEST_UNIT_READY; break; @@ -492,9 +493,28 @@ static USBH_StatusTypeDef USBH_MSC_Process(USBH_HandleTypeDef *phost) break; case MSC_IDLE: - error = USBH_OK; - break; - + error = USBH_OK; + break; + + case MSC_READ: + case MSC_WRITE: + error = USBH_MSC_RdWrProcess(phost, MSC_Handle->rw_lun); + if(((int32_t)(phost->Timer - MSC_Handle->timeout) > 0) || (phost->device.is_connected == 0)) + { + error = USBH_FAIL; + } + + if (error != USBH_BUSY) + { + MSC_Handle->state = MSC_IDLE; + if (MSC_Handle->RdWrCompleteCallback != NULL) + { + MSC_Handle->RdWrCompleteCallback(error); + MSC_Handle->RdWrCompleteCallback = NULL; + } + } + break; + default: break; } @@ -531,12 +551,12 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ { case MSC_READ: - scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, NULL, 0) ; + scsi_status = USBH_MSC_SCSI_Read(phost,lun, 0, 0) ; if(scsi_status == USBH_OK) { MSC_Handle->unit[lun].state = MSC_IDLE; - error = USBH_OK; + error = USBH_OK; } else if( scsi_status == USBH_FAIL) { @@ -545,7 +565,7 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; - error = USBH_FAIL; + error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); @@ -553,7 +573,7 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ break; case MSC_WRITE: - scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, NULL, 0) ; + scsi_status = USBH_MSC_SCSI_Write(phost,lun, 0, 0) ; if(scsi_status == USBH_OK) { @@ -567,7 +587,7 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ else if(scsi_status == USBH_UNRECOVERED_ERROR) { MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; - error = USBH_FAIL; + error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); @@ -584,7 +604,6 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ USBH_UsrLog ("Additional Sense Code Qualifier: %x", MSC_Handle->unit[lun].sense.ascq); MSC_Handle->unit[lun].state = MSC_IDLE; MSC_Handle->unit[lun].error = MSC_ERROR; - error = USBH_FAIL; } if( scsi_status == USBH_FAIL) @@ -593,8 +612,8 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ } else if(scsi_status == USBH_UNRECOVERED_ERROR) { - MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; - error = USBH_FAIL; + MSC_Handle->unit[lun].state = MSC_UNRECOVERED_ERROR; + error = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); @@ -608,6 +627,7 @@ static USBH_StatusTypeDef USBH_MSC_RdWrProcess(USBH_HandleTypeDef *phost, uint8_ return error; } + /** * @brief USBH_MSC_IsReady * The function check if the MSC function is ready @@ -700,41 +720,34 @@ USBH_StatusTypeDef USBH_MSC_GetLUNInfo(USBH_HandleTypeDef *phost, uint8_t lun, M USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, - uint32_t length) + uint32_t length, + MSC_RdWrCompleteCallback callback) { - uint32_t timeout; MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; if ((phost->device.is_connected == 0) || - (phost->gState != HOST_CLASS) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE) || (MSC_Handle->unit[lun].state != MSC_IDLE)) { return USBH_FAIL; } + MSC_Handle->state = MSC_READ; MSC_Handle->unit[lun].state = MSC_READ; MSC_Handle->rw_lun = lun; + MSC_Handle->RdWrCompleteCallback = callback; + MSC_Handle->timeout = phost->Timer + (length * MSC_TIMEOUT_FRAMES_PER_BLOCK); + USBH_MSC_SCSI_Read(phost, lun, address, - pbuf, length); - - timeout = phost->Timer; - - while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) - { - if(((phost->Timer - timeout) > (10000 * length)) || (phost->device.is_connected == 0)) - { - MSC_Handle->state = MSC_IDLE; - return USBH_FAIL; - } - } - MSC_Handle->state = MSC_IDLE; return USBH_OK; } + + /** * @brief USBH_MSC_Write * The function performs a Write operation @@ -748,37 +761,29 @@ USBH_StatusTypeDef USBH_MSC_Read(USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_MSC_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, - uint32_t length) + uint32_t length, + MSC_RdWrCompleteCallback callback) { - uint32_t timeout; MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; if ((phost->device.is_connected == 0) || - (phost->gState != HOST_CLASS) || + (phost->gState != HOST_CLASS) || + (MSC_Handle->state != MSC_IDLE) || (MSC_Handle->unit[lun].state != MSC_IDLE)) { return USBH_FAIL; } + MSC_Handle->state = MSC_WRITE; MSC_Handle->unit[lun].state = MSC_WRITE; MSC_Handle->rw_lun = lun; + MSC_Handle->RdWrCompleteCallback = callback; + MSC_Handle->timeout = phost->Timer + (length * MSC_TIMEOUT_FRAMES_PER_BLOCK); + USBH_MSC_SCSI_Write(phost, lun, address, - pbuf, length); - - timeout = phost->Timer; - while (USBH_MSC_RdWrProcess(phost, lun) == USBH_BUSY) - { - if(((phost->Timer - timeout) > (10000 * length)) || (phost->device.is_connected == 0)) - { - MSC_Handle->state = MSC_IDLE; - return USBH_FAIL; - } - } - MSC_Handle->state = MSC_IDLE; return USBH_OK; } diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c index 2aef67f..a9b7ec4 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_bot.c @@ -28,77 +28,23 @@ /* Includes ------------------------------------------------------------------*/ #include "usbh_msc_bot.h" #include "usbh_msc.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 -* @{ -*/ -/** -* @} -*/ +#include "downstream_spi.h" +#include "downstream_msc.h" -/** @defgroup USBH_MSC_BOT_Private_Variables -* @{ -*/ - -/** -* @} -*/ - -/** @defgroup USBH_MSC_BOT_Private_FunctionPrototypes -* @{ -*/ static USBH_StatusTypeDef USBH_MSC_BOT_Abort(USBH_HandleTypeDef *phost, uint8_t lun, uint8_t dir); static BOT_CSWStatusTypeDef USBH_MSC_DecodeCSW(USBH_HandleTypeDef *phost); -/** -* @} -*/ - +void USBH_MSC_BOT_Read_FreePacketCallback(DownstreamPacketTypeDef* freePacket); +void USBH_MSC_BOT_Read_PrepareURB(USBH_HandleTypeDef *phost); +void USBH_MSC_BOT_Write_ReceivePacketCallback(HAL_StatusTypeDef result, + DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength); +void USBH_MSC_BOT_Write_PrepareURB(USBH_HandleTypeDef *phost); -/** @defgroup USBH_MSC_BOT_Exported_Variables -* @{ -*/ -/** -* @} -*/ +USBH_HandleTypeDef *Callback_MSC_phost; -/** @defgroup USBH_MSC_BOT_Private_Functions -* @{ -*/ /** * @brief USBH_MSC_BOT_REQ_Reset @@ -189,7 +135,6 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) BOT_CBW_LENGTH, MSC_Handle->OutPipe, 1); - break; case BOT_SEND_CBW_WAIT: @@ -217,75 +162,68 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) {/* If there is NO Data Transfer Stage */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send CBW */ MSC_Handle->hbot.state = BOT_SEND_CBW; -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_OUT; -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } break; case BOT_DATA_IN: /* Get first packet */ - USBH_BulkReceiveData (phost, - MSC_Handle->hbot.pbuf, - MSC_Handle->InEpSize , //Todo: Possible buffer overflow here? - MSC_Handle->InPipe); - - MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; - - break; + Callback_MSC_phost = phost; + Downstream_GetFreePacket(USBH_MSC_BOT_Read_FreePacketCallback); + MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; + break; case BOT_DATA_IN_WAIT: - URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); - - if(URB_Status == USBH_URB_DONE) + + if (URB_Status == USBH_URB_DONE) { - /* Adjust Data pointer and data length */ - if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize) - { - MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize; - MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize; - } - else - { - MSC_Handle->hbot.cbw.field.DataTransferLength = 0; - } - - /* More Data To be Received */ - if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) - { - /* Get next packet */ - USBH_BulkReceiveData (phost, - MSC_Handle->hbot.pbuf, - MSC_Handle->InEpSize , //Todo: Possible buffer overflow here? - MSC_Handle->InPipe); - - } - else - { - /* If value was 0, and successful transfer, then change the state */ - MSC_Handle->hbot.state = BOT_RECEIVE_CSW; -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif - } + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size; + MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size; + + if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0) + { + //End of reception: dispatch last packet + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + Downstream_MSC_PutStreamDataPacket(MSC_Handle->hbot.bot_packet, + (BOT_PAGE_LENGTH - MSC_Handle->hbot.bot_packet_bytes_remaining)); + } + else + { + //Still more data to receive + if (MSC_Handle->hbot.bot_packet_bytes_remaining == 0) + { + //Dispatch current bot_packet, then get a new one + if (Downstream_MSC_PutStreamDataPacket(MSC_Handle->hbot.bot_packet, + (BOT_PAGE_LENGTH - MSC_Handle->hbot.bot_packet_bytes_remaining)) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + break; + } + if (Downstream_GetFreePacket(USBH_MSC_BOT_Read_FreePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + break; + } + } + else + { + //Continue filling the current bot_packet + MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size; + USBH_MSC_BOT_Read_PrepareURB(phost); + } + } } + else if(URB_Status == USBH_URB_STALL) { /* This is Data IN Stage STALL Condition */ @@ -297,67 +235,56 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) The host shall accept the data received. The host shall clear the Bulk-In pipe. 4. The host shall attempt to receive a CSW.*/ - -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } break; case BOT_DATA_OUT: - - USBH_BulkSendData (phost, - MSC_Handle->hbot.pbuf, - MSC_Handle->OutEpSize , //?????????? - MSC_Handle->OutPipe, - 1); - - - MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; - break; + Callback_MSC_phost = phost; + MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; + if (Downstream_MSC_GetStreamDataPacket(USBH_MSC_BOT_Write_ReceivePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + } + break; case BOT_DATA_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); if(URB_Status == USBH_URB_DONE) { - /* Adjust Data pointer and data length */ - if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize) - { - MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize; - MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; - } - else - { - MSC_Handle->hbot.cbw.field.DataTransferLength = 0; - } - - /* More Data To be Sent */ - if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) - { - USBH_BulkSendData (phost, - MSC_Handle->hbot.pbuf, - MSC_Handle->OutEpSize , //????????????? - MSC_Handle->OutPipe, - 1); - } - else - { - /* If value was 0, and successful transfer, then change the state */ - MSC_Handle->hbot.state = BOT_RECEIVE_CSW; - } -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif + MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->hbot.this_URB_size; + MSC_Handle->hbot.bot_packet_bytes_remaining -= MSC_Handle->hbot.this_URB_size; + + if (MSC_Handle->hbot.cbw.field.DataTransferLength == 0) + { + //End of reception + MSC_Handle->hbot.state = BOT_RECEIVE_CSW; + } + else + { + //Still more data to receive + if (MSC_Handle->hbot.bot_packet_bytes_remaining == 0) + { + //Get next bot_packet + if (Downstream_MSC_GetStreamDataPacket(USBH_MSC_BOT_Write_ReceivePacketCallback) != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_IN; + break; + } + } + else + { + //Continue reading the current bot_packet + MSC_Handle->hbot.pbuf += MSC_Handle->hbot.this_URB_size; + USBH_MSC_BOT_Write_PrepareURB(phost); + } + } } else if(URB_Status == USBH_URB_NOTREADY) { /* Resend same data */ MSC_Handle->hbot.state = BOT_DATA_OUT; -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } else if(URB_Status == USBH_URB_STALL) @@ -369,10 +296,7 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) 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. - */ -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif + */ } break; @@ -405,16 +329,10 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) { status = USBH_FAIL; } -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_IN; -#if (USBH_USE_OS == 1) - osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); -#endif } break; @@ -464,6 +382,79 @@ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) return status; } + +void USBH_MSC_BOT_Read_FreePacketCallback(DownstreamPacketTypeDef* freePacket) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + + MSC_Handle->hbot.bot_packet = freePacket; + MSC_Handle->hbot.pbuf = freePacket->Data; + MSC_Handle->hbot.bot_packet_bytes_remaining = BOT_PAGE_LENGTH; + USBH_MSC_BOT_Read_PrepareURB(Callback_MSC_phost); +} + + +void USBH_MSC_BOT_Read_PrepareURB(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + MSC_Handle->hbot.this_URB_size = MSC_Handle->hbot.cbw.field.DataTransferLength; + if (MSC_Handle->hbot.this_URB_size > MSC_Handle->hbot.bot_packet_bytes_remaining) + { + MSC_Handle->hbot.this_URB_size = MSC_Handle->hbot.bot_packet_bytes_remaining; + } + if (MSC_Handle->hbot.this_URB_size > MSC_Handle->InEpSize) + { + MSC_Handle->hbot.this_URB_size = MSC_Handle->InEpSize; + } + + USBH_BulkReceiveData(phost, + MSC_Handle->hbot.pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->InPipe); +} + + +void USBH_MSC_BOT_Write_ReceivePacketCallback(HAL_StatusTypeDef result, + DownstreamPacketTypeDef* receivedPacket, + uint16_t dataLength) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) Callback_MSC_phost->pActiveClass->pData; + + if (result != HAL_OK) + { + MSC_Handle->hbot.state = BOT_ERROR_OUT; + return; + } + + MSC_Handle->hbot.bot_packet = receivedPacket; + MSC_Handle->hbot.pbuf = receivedPacket->Data; + MSC_Handle->hbot.bot_packet_bytes_remaining = dataLength; + USBH_MSC_BOT_Write_PrepareURB(Callback_MSC_phost); +} + + +void USBH_MSC_BOT_Write_PrepareURB(USBH_HandleTypeDef *phost) +{ + MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; + + MSC_Handle->hbot.this_URB_size = MSC_Handle->hbot.cbw.field.DataTransferLength; + if (MSC_Handle->hbot.this_URB_size > MSC_Handle->hbot.bot_packet_bytes_remaining) + { + MSC_Handle->hbot.this_URB_size = MSC_Handle->hbot.bot_packet_bytes_remaining; + } + if (MSC_Handle->hbot.this_URB_size > MSC_Handle->OutEpSize) + { + MSC_Handle->hbot.this_URB_size = MSC_Handle->OutEpSize; + } + USBH_BulkSendData (phost, + MSC_Handle->hbot.pbuf, + MSC_Handle->hbot.this_URB_size, + MSC_Handle->OutPipe, + 1); +} + + /** * @brief USBH_MSC_BOT_Abort * The function handle the BOT Abort process. diff --git a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c index 793232a..d4122fa 100644 --- a/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c +++ b/Downstream/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Src/usbh_msc_scsi.c @@ -292,10 +292,9 @@ USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, break; case BOT_CMD_WAIT: - + error = USBH_MSC_BOT_Process(phost, lun); - - if(error == USBH_OK) + if (error == USBH_OK) { sense_data->key = MSC_Handle->hbot.pbuf[2] & 0x0F; sense_data->asc = MSC_Handle->hbot.pbuf[12]; @@ -323,7 +322,6 @@ USBH_StatusTypeDef USBH_MSC_SCSI_RequestSense (USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, uint32_t length) { USBH_StatusTypeDef error = USBH_FAIL ; @@ -335,7 +333,7 @@ USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ - MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512; + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[lun].capacity.block_size; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_OUT; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; @@ -348,15 +346,12 @@ USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); - /*Transfer length */ MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; - MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; - MSC_Handle->hbot.pbuf = pbuf; error = USBH_BUSY; break; @@ -384,7 +379,6 @@ USBH_StatusTypeDef USBH_MSC_SCSI_Write(USBH_HandleTypeDef *phost, USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, uint8_t lun, uint32_t address, - uint8_t *pbuf, uint32_t length) { USBH_StatusTypeDef error = USBH_FAIL ; @@ -395,7 +389,7 @@ USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, case BOT_CMD_SEND: /*Prepare the CBW and relevent field*/ - MSC_Handle->hbot.cbw.field.DataTransferLength = length * 512; + MSC_Handle->hbot.cbw.field.DataTransferLength = length * MSC_Handle->unit[lun].capacity.block_size;; MSC_Handle->hbot.cbw.field.Flags = USB_EP_DIR_IN; MSC_Handle->hbot.cbw.field.CBLength = CBW_LENGTH; @@ -408,15 +402,12 @@ USBH_StatusTypeDef USBH_MSC_SCSI_Read(USBH_HandleTypeDef *phost, MSC_Handle->hbot.cbw.field.CB[4] = (((uint8_t*)&address)[1]); MSC_Handle->hbot.cbw.field.CB[5] = (((uint8_t*)&address)[0]); - /*Transfer length */ MSC_Handle->hbot.cbw.field.CB[7] = (((uint8_t *)&length)[1]) ; MSC_Handle->hbot.cbw.field.CB[8] = (((uint8_t *)&length)[0]) ; - MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_WAIT; - MSC_Handle->hbot.pbuf = pbuf; error = USBH_BUSY; break; diff --git a/Downstream/Src/downstream_msc.c b/Downstream/Src/downstream_msc.c index a721cbe..ce6c421 100644 --- a/Downstream/Src/downstream_msc.c +++ b/Downstream/Src/downstream_msc.c @@ -9,16 +9,26 @@ #include "downstream_msc.h" #include "downstream_interface_def.h" #include "downstream_statemachine.h" +#include "downstream_spi.h" #include "usbh_msc.h" extern USBH_HandleTypeDef hUsbHostFS; //Hard-link ourselves to usb_host.c +//Stuff we need to save for our callbacks to use: +DownstreamMSCCallbackPacketTypeDef GetStreamDataCallback; +uint32_t ByteCount; +DownstreamPacketTypeDef* ReadStreamPacket; +uint8_t ReadStreamBusy; + + void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket); void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receivedPacket); void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket); - +void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* receivedPacket); +void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef result); +void Downstream_MSC_GetStreamDataPacketCallback(DownstreamPacketTypeDef* replyPacket); //High-level checks on the connected device. We don't want some weirdly @@ -27,14 +37,16 @@ HAL_StatusTypeDef Downstream_MSC_ApproveConnectedDevice(void) { MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; - if ((MSC_Handle->unit[0].capacity.block_nbr == 0) || - (MSC_Handle->unit[0].capacity.block_nbr == UINT32_MAX)) + if ((MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == 0) || + (MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr == UINT32_MAX)) { + //FreakOut????? return HAL_ERROR; } - if (MSC_Handle->unit[0].capacity.block_size != 512) + if (MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size != MSC_SUPPORTED_BLOCK_SIZE) { + //FreakOut????? return HAL_ERROR; } @@ -58,7 +70,12 @@ void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) Downstream_MSC_PacketProcessor_BeginRead(receivedPacket); break; + case COMMAND_MSC_BEGIN_WRITE: + Downstream_MSC_PacketProcessor_BeginWrite(receivedPacket); + break; + default: + //FreakOut????? Downstream_PacketProcessor_ErrorReply(receivedPacket); } @@ -67,7 +84,7 @@ void Downstream_MSC_PacketProcessor(DownstreamPacketTypeDef* receivedPacket) void Downstream_MSC_PacketProcessor_TestUnitReady(DownstreamPacketTypeDef* receivedPacket) { - if (USBH_MSC_UnitIsReady(&hUsbHostFS, 0)) + if (USBH_MSC_UnitIsReady(&hUsbHostFS, MSC_FIXED_LUN)) { receivedPacket->Data[0] = HAL_OK; } @@ -85,8 +102,8 @@ void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receive MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 8; - *(uint32_t*)&(receivedPacket->Data[0]) = MSC_Handle->unit[0].capacity.block_nbr; - *(uint32_t*)&(receivedPacket->Data[4]) = (uint32_t)MSC_Handle->unit[0].capacity.block_size; + *(uint32_t*)&(receivedPacket->Data[0]) = MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr; + *(uint32_t*)&(receivedPacket->Data[4]) = (uint32_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; Downstream_PacketProcessor_ClassReply(receivedPacket); } @@ -94,39 +111,167 @@ void Downstream_MSC_PacketProcessor_GetCapacity(DownstreamPacketTypeDef* receive void Downstream_MSC_PacketProcessor_BeginRead(DownstreamPacketTypeDef* receivedPacket) { - uint64_t address; - uint32_t count; + uint64_t readBlockAddress; + uint32_t readBlockCount; + uint64_t readByteCount; MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; if (receivedPacket->Length != (DOWNSTREAM_PACKET_HEADER_LEN + (4 * 3))) { + //FreakOut????? Downstream_PacketProcessor_ErrorReply(receivedPacket); return; } - address = *(uint64_t*)&(receivedPacket->Data[0]); - count = *(uint32_t*)&(receivedPacket->Data[8]); - if ((address >= (uint64_t)MSC_Handle->unit[0].capacity.block_nbr) || - ((address + count - 1) >= (uint64_t)MSC_Handle->unit[0].capacity.block_nbr)) + readBlockAddress = *(uint64_t*)&(receivedPacket->Data[0]); + readBlockCount = *(uint32_t*)&(receivedPacket->Data[8]); + readByteCount = readBlockCount * MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; + if ((readBlockAddress >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + ((readBlockAddress + readBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + (readByteCount > UINT32_MAX)) { + //FreakOut????? Downstream_PacketProcessor_ErrorReply(receivedPacket); return; } - if (USBH_MSC_UnitIsReady(&hUsbHostFS, 0)) + receivedPacket->Data[0] = HAL_ERROR; + receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 1; + if (USBH_MSC_UnitIsReady(&hUsbHostFS, MSC_FIXED_LUN)) { - receivedPacket->Data[0] = HAL_OK; + if (USBH_MSC_Read(&hUsbHostFS, + MSC_FIXED_LUN, + (uint32_t)readBlockAddress, + readBlockCount, + Downstream_MSC_PacketProcessor_RdWrCompleteCallback) == USBH_OK) + { + receivedPacket->Data[0] = HAL_OK; + } } - else + Downstream_TransmitPacket(receivedPacket); +} + + +void Downstream_MSC_PacketProcessor_RdWrCompleteCallback(USBH_StatusTypeDef result) +{ + if (result != USBH_OK) { - receivedPacket->Data[0] = HAL_ERROR; + Downstream_GetFreePacket(Downstream_PacketProcessor_ErrorReply); + return; + } + Downstream_ReceivePacket(Downstream_PacketProcessor); +} + + + +void Downstream_MSC_PacketProcessor_BeginWrite(DownstreamPacketTypeDef* receivedPacket) +{ + uint64_t writeBlockAddress; + uint32_t writeBlockCount; + uint64_t writeByteCount; + MSC_HandleTypeDef* MSC_Handle = (MSC_HandleTypeDef*)hUsbHostFS.pActiveClass->pData; + + if (receivedPacket->Length != (DOWNSTREAM_PACKET_HEADER_LEN + (4 * 3))) + { + //FreakOut????? + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; + } + + writeBlockAddress = *(uint64_t*)&(receivedPacket->Data[0]); + writeBlockCount = *(uint32_t*)&(receivedPacket->Data[8]); + writeByteCount = writeBlockCount * MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_size; + if ((writeBlockAddress >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + ((writeBlockAddress + writeBlockCount - 1) >= (uint64_t)MSC_Handle->unit[MSC_FIXED_LUN].capacity.block_nbr) || + (writeByteCount > UINT32_MAX)) + { + //FreakOut????? + Downstream_PacketProcessor_ErrorReply(receivedPacket); + return; } + + ReadStreamPacket = NULL; //Prepare for GetStreamDataPacket's use + ReadStreamBusy = 0; + ByteCount = (uint32_t)writeByteCount; + + receivedPacket->Data[0] = HAL_ERROR; receivedPacket->Length = DOWNSTREAM_PACKET_HEADER_LEN + 1; + + //Our host stack has no way to detect if write-protection is enabled. + //So currently we can't return HAL_BUSY to Upstream in this situation. + if (USBH_MSC_UnitIsReady(&hUsbHostFS, MSC_FIXED_LUN)) + { + if (USBH_MSC_Write(&hUsbHostFS, + MSC_FIXED_LUN, + (uint32_t)writeBlockAddress, + writeBlockCount, + Downstream_MSC_PacketProcessor_RdWrCompleteCallback) == USBH_OK) + { + receivedPacket->Data[0] = HAL_OK; + } + } Downstream_TransmitPacket(receivedPacket); +} + + + +HAL_StatusTypeDef Downstream_MSC_PutStreamDataPacket(DownstreamPacketTypeDef* packetToSend, + uint32_t dataLength) +{ + packetToSend->Length = dataLength + DOWNSTREAM_PACKET_HEADER_LEN; + packetToSend->CommandClass = COMMAND_CLASS_MASS_STORAGE | COMMAND_CLASS_DATA_FLAG; + packetToSend->Command = COMMAND_MSC_BEGIN_WRITE; + return Downstream_TransmitPacket(packetToSend); +} + + +HAL_StatusTypeDef Downstream_MSC_GetStreamDataPacket(DownstreamMSCCallbackPacketTypeDef callback) +{ + GetStreamDataCallback = callback; + + if (ReadStreamBusy != 0) + { + return HAL_OK; + } + ReadStreamBusy = 1; + + if (ReadStreamPacket && GetStreamDataCallback) //Do we have a stored packet and an address to send it? + { + Downstream_MSC_GetStreamDataPacketCallback(ReadStreamPacket); //Send it now! + ReadStreamPacket = NULL; + return HAL_OK; //Our callback will call us again, so we don't need to get a packet in this case. + } + return Downstream_ReceivePacket(Downstream_MSC_GetStreamDataPacketCallback); +} + + +void Downstream_MSC_GetStreamDataPacketCallback(DownstreamPacketTypeDef* replyPacket) +{ + uint16_t dataLength; + + ReadStreamBusy = 0; + if (GetStreamDataCallback == NULL) + { + ReadStreamPacket = replyPacket; //We used up our callback already, so save this one for later. + return; + } + + if (((replyPacket->CommandClass & COMMAND_CLASS_DATA_FLAG) == 0) || //Any incoming 'command' (as opposed to incoming 'data') is an automatic fail here + (replyPacket->Length <= DOWNSTREAM_PACKET_HEADER_LEN) || //Should be at least one data byte in the packet. + (replyPacket->Length > ByteCount)) + { + //FreakOut????? + GetStreamDataCallback(HAL_ERROR, NULL, NULL); + return; + } + + dataLength = replyPacket->Length - DOWNSTREAM_PACKET_HEADER_LEN; + ByteCount -= dataLength; + GetStreamDataCallback(HAL_OK, replyPacket, dataLength); //usb_msc_scsi will use this packet, so don't release now + if (ByteCount > 0) + { + Downstream_MSC_GetStreamDataPacket(NULL); //Try to get the next packet now, before USB asks for it + } - USBH_MSC_Read(&hUsbHostFS, - 0, - (uint32_t)address, - count); } diff --git a/Downstream/Src/downstream_spi.c b/Downstream/Src/downstream_spi.c index 561ccb8..d4e07a4 100644 --- a/Downstream/Src/downstream_spi.c +++ b/Downstream/Src/downstream_spi.c @@ -15,6 +15,7 @@ SPI_HandleTypeDef Hspi1; DownstreamPacketTypeDef DownstreamPacket0; DownstreamPacketTypeDef DownstreamPacket1; DownstreamPacketTypeDef* CurrentWorkingPacket; +DownstreamPacketTypeDef* NextTxPacket; InterfaceStateTypeDef DownstreamInterfaceState; FreePacketCallbackTypeDef PendingFreePacketCallback; //Indicates someone is waiting for a packet buffer to become available @@ -34,7 +35,7 @@ void Downstream_InitSPI(void) DownstreamPacket0.Busy = NOT_BUSY; DownstreamPacket1.Busy = NOT_BUSY; - //NextTxPacket = NULL; + NextTxPacket = NULL; PendingFreePacketCallback = NULL; ReceivePacketCallback = NULL; @@ -147,7 +148,7 @@ void Downstream_ReleasePacket(DownstreamPacketTypeDef* packetToRelease) //Used by Downstream state machine (and USB classes?). //Ok to call when idle or transmitting. -//Not OK to call when receiving or waiting for downstream reply. +//Not OK to call when receiving or awaiting reception. HAL_StatusTypeDef Downstream_ReceivePacket(SpiPacketReceivedCallbackTypeDef callback) { if (ReceivePacketCallback != NULL) @@ -248,7 +249,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) //Used by Downstream state machine (and USB classes?). -//Call when idle only. +//Call when idle or transmitting. +//It doesn't make sense to call when receiving or awaiting reception. HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWrite) { //Sanity checks @@ -263,30 +265,42 @@ HAL_StatusTypeDef Downstream_TransmitPacket(DownstreamPacketTypeDef* packetToWri { SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR; } - - if (DownstreamInterfaceState != DOWNSTREAM_INTERFACE_IDLE) + if (NextTxPacket != NULL) { SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR; } - DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_SIZE_WAIT; - CurrentWorkingPacket = packetToWrite; - if (HAL_SPI_TransmitReceive_DMA(&Hspi1, - (uint8_t*)&CurrentWorkingPacket->Length, - (uint8_t*)&CurrentWorkingPacket->Length, - 2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1" + switch (DownstreamInterfaceState) { - SPI_INTERFACE_FREAKOUT_RETURN_VOID; + case DOWNSTREAM_INTERFACE_TX_SIZE_WAIT: + case DOWNSTREAM_INTERFACE_TX_PACKET_WAIT: + NextTxPacket = packetToWrite; + break; + + case DOWNSTREAM_INTERFACE_IDLE: + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_SIZE_WAIT; + CurrentWorkingPacket = packetToWrite; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length, + (uint8_t*)&CurrentWorkingPacket->Length, + 2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1" + { + SPI_INTERFACE_FREAKOUT_RETURN_VOID; + } + UPSTREAM_TX_REQUEST_ASSERT; + break; + + default: + SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR; } - UPSTREAM_TX_REQUEST_ASSERT; return HAL_OK; } //Called at the end of the SPI TxRx DMA transfer, //at DMA2 interrupt priority. Assume *hspi points to our hspi1. -//We use TxRx while sending our reply packet to check if Upstream was trying +//We use TxRx to send our reply packet to check if Upstream was trying //to send us a packet at the same time. void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { @@ -326,8 +340,26 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) SPI_INTERFACE_FREAKOUT_RETURN_VOID; } - DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; Downstream_ReleasePacket(CurrentWorkingPacket); + if (NextTxPacket != NULL) + { + //NextTxPacket has already passed the checks in Downstream_TransmitPacket. + //So we just need to pass it to HAL_SPI_Transmit_DMA. + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_TX_SIZE_WAIT; + CurrentWorkingPacket = NextTxPacket; + NextTxPacket = NULL; + if (HAL_SPI_TransmitReceive_DMA(&Hspi1, + (uint8_t*)&CurrentWorkingPacket->Length, + (uint8_t*)&CurrentWorkingPacket->Length, + 2 + 1) != HAL_OK) //"When the CRC feature is enabled the pRxData Length must be Size + 1" + { + SPI_INTERFACE_FREAKOUT_RETURN_VOID; + } + UPSTREAM_TX_REQUEST_ASSERT; + return; + } + + DownstreamInterfaceState = DOWNSTREAM_INTERFACE_IDLE; if (ReceivePacketCallback != NULL) { Downstream_CheckPreparePacketReception(); diff --git a/Downstream/Src/downstream_statemachine.c b/Downstream/Src/downstream_statemachine.c index 3a9f97a..d4a827a 100644 --- a/Downstream/Src/downstream_statemachine.c +++ b/Downstream/Src/downstream_statemachine.c @@ -19,7 +19,6 @@ DownstreamStateTypeDef DownstreamState; InterfaceCommandClassTypeDef ConfiguredDeviceClass; -void Downstream_PacketProcessor(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_Interface(DownstreamPacketTypeDef* receivedPacket); void Downstream_PacketProcessor_Interface_ReplyNotifyDevice(DownstreamPacketTypeDef* replyPacket); diff --git a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c index 2276c1d..c512133 100755 --- a/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c +++ b/Upstream/Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Src/usbd_msc_scsi.c @@ -846,7 +846,8 @@ static void SCSI_Verify10(void) */ static int8_t SCSI_CheckAddressRange (uint32_t blk_offset , uint16_t blk_nbr) { - if ((blk_offset + blk_nbr) > SCSI_ProcessCmd_hmsc->scsi_blk_nbr ) + if ((blk_offset > SCSI_ProcessCmd_hmsc->scsi_blk_nbr) || + ((blk_offset + blk_nbr) > SCSI_ProcessCmd_hmsc->scsi_blk_nbr)) { SCSI_SenseCode(SCSI_ProcessCmd_pdev, SCSI_ProcessCmd_lun, diff --git a/Upstream/Src/upstream_msc.c b/Upstream/Src/upstream_msc.c index 016b22a..56074df 100644 --- a/Upstream/Src/upstream_msc.c +++ b/Upstream/Src/upstream_msc.c @@ -51,7 +51,7 @@ HAL_StatusTypeDef Upstream_MSC_TestReady(UpstreamMSCCallbackTypeDef callback) void Upstream_MSC_TestReadyReplyCallback(UpstreamPacketTypeDef* replyPacket) { if ((replyPacket->Length != (UPSTREAM_PACKET_HEADER_LEN + 1)) || - (replyPacket->CommandClass & COMMAND_CLASS_DATA_FLAG) || + (replyPacket->CommandClass != COMMAND_CLASS_MASS_STORAGE) || (replyPacket->Data[0] != HAL_OK)) { Upstream_ReleasePacket(replyPacket); @@ -90,7 +90,7 @@ void Upstream_MSC_GetCapacityReplyCallback(UpstreamPacketTypeDef* replyPacket) uint32_t uint[2]; if ((replyPacket->Length != (UPSTREAM_PACKET_HEADER_LEN + 8) || - (replyPacket->CommandClass & COMMAND_CLASS_DATA_FLAG))) + (replyPacket->CommandClass != COMMAND_CLASS_MASS_STORAGE))) { GetCapacityCallback(HAL_ERROR, NULL, NULL); return; @@ -113,9 +113,9 @@ HAL_StatusTypeDef Upstream_MSC_BeginRead(UpstreamMSCCallbackTypeDef callback, ReadStreamPacket = NULL; //Prepare for GetStreamDataPacket's use ReadStreamBusy = 0; + ByteCount = readByteCount; TestReadyCallback = callback; - ByteCount = readByteCount; freePacket = Upstream_GetFreePacketImmediately(); freePacket->Length = UPSTREAM_PACKET_HEADER_LEN + (4 * 3); @@ -165,20 +165,21 @@ void Upstream_MSC_GetStreamDataPacketCallback(UpstreamPacketTypeDef* replyPacket return; } + dataLength = replyPacket->Length - UPSTREAM_PACKET_HEADER_LEN; + if (((replyPacket->CommandClass & COMMAND_CLASS_DATA_FLAG) == 0) || //Any 'command' reply (as opposed to 'data' reply) is an automatic fail here (replyPacket->Length <= UPSTREAM_PACKET_HEADER_LEN) || //Should be at least one data byte in the reply. - (replyPacket->Length > ByteCount)) + (dataLength > ByteCount)) //No more data than expected transfer length { GetStreamDataCallback(HAL_ERROR, NULL, NULL); return; } - dataLength = replyPacket->Length - UPSTREAM_PACKET_HEADER_LEN; ByteCount -= dataLength; GetStreamDataCallback(HAL_OK, replyPacket, dataLength); //usb_msc_scsi will use this packet, so don't release now if (ByteCount > 0) { - Upstream_MSC_GetStreamDataPacket(NULL); //Try to get the next packet now, before USB asks for it + Upstream_MSC_GetStreamDataPacket(NULL); //Try to get the next packet now, before USB asks for it } } @@ -212,7 +213,7 @@ HAL_StatusTypeDef Upstream_MSC_BeginWrite(UpstreamMSCCallbackTypeDef callback, void Upstream_MSC_BeginWriteReplyCallback(UpstreamPacketTypeDef* replyPacket) { if ((replyPacket->Length != (UPSTREAM_PACKET_HEADER_LEN + 1)) || - (replyPacket->CommandClass & COMMAND_CLASS_DATA_FLAG) || + (replyPacket->CommandClass != COMMAND_CLASS_MASS_STORAGE) || ((replyPacket->Data[0] != HAL_OK) && (replyPacket->Data[0] != HAL_BUSY))) { Upstream_ReleasePacket(replyPacket); diff --git a/Upstream/Src/upstream_msc_mock.c b/Upstream/Src/upstream_msc_mock.c index 6cdb0ef..7e5eb87 100644 --- a/Upstream/Src/upstream_msc_mock.c +++ b/Upstream/Src/upstream_msc_mock.c @@ -5,7 +5,7 @@ * Author: Robert Fisk * * This file replaces upstream_msc.c to allow operational testing of Upstream, - * without Upstream in place and communicating over SPI. + * without Downstream in place and communicating over SPI. * It still attempts to write downstream packets out the SPI port. */ diff --git a/Upstream/Src/upstream_spi.c b/Upstream/Src/upstream_spi.c index d266e10..9ae9ced 100644 --- a/Upstream/Src/upstream_spi.c +++ b/Upstream/Src/upstream_spi.c @@ -159,7 +159,8 @@ void Upstream_ReleasePacket(UpstreamPacketTypeDef* packetToRelease) //Used by USB interface classes only. //OK to call when still transmitting another packet. -//Not OK to call when receiving or waiting for downstream reply. +//Not OK to call when receiving or waiting for downstream reply, +//as we can't let the size/packet sequence get out of sync. HAL_StatusTypeDef Upstream_TransmitPacket(UpstreamPacketTypeDef* packetToWrite) { //Sanity checks @@ -188,13 +189,6 @@ HAL_StatusTypeDef Upstream_TransmitPacket(UpstreamPacketTypeDef* packetToWrite) NextTxPacket = packetToWrite; break; - case UPSTREAM_INTERFACE_RX_SIZE_WAIT: - case UPSTREAM_INTERFACE_RX_SIZE: - case UPSTREAM_INTERFACE_RX_PACKET_WAIT: - case UPSTREAM_INTERFACE_RX_PACKET: - //We can't let the size/packet sequence get out of sync. - SPI_INTERFACE_FREAKOUT_RETURN_HAL_ERROR; - case UPSTREAM_INTERFACE_IDLE: UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT; CurrentWorkingPacket = packetToWrite; @@ -238,7 +232,7 @@ void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) Upstream_ReleasePacket(CurrentWorkingPacket); if (NextTxPacket != NULL) { - //NextTxPacket has already passed the checks in SendUpstreamPacket. + //NextTxPacket has already passed the checks in Upstream_TransmitPacket. //So we just need to pass it to HAL_SPI_Transmit_DMA. UpstreamInterfaceState = UPSTREAM_INTERFACE_TX_SIZE_WAIT; CurrentWorkingPacket = NextTxPacket; @@ -385,7 +379,8 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) if (UpstreamInterfaceState == UPSTREAM_INTERFACE_RX_PACKET) { UpstreamInterfaceState = UPSTREAM_INTERFACE_IDLE; - if ((SentCommandClass != (CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK)) || + if (((SentCommandClass != (CurrentWorkingPacket->CommandClass & COMMAND_CLASS_MASK)) && + (SentCommandClass != COMMAND_CLASS_ERROR)) || (SentCommand != CurrentWorkingPacket->Command)) { SPI_INTERFACE_FREAKOUT_RETURN_VOID;