Full implementation of Downstream MSC interface, including significant

modifications to USB host MSC.

Also, minor tweaks to Upstream.
pull/7/head
Robert Fisk 9 years ago
parent b9b6123642
commit 0e1fed6047

@ -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);

@ -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);

@ -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);
/**
* @}
*/

@ -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;

@ -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);

@ -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;
}

@ -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.

@ -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;

@ -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);
}

@ -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();

@ -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);

@ -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,

@ -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);

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

@ -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;

Loading…
Cancel
Save