diff --git a/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c b/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c index 01553354d4..c9120d596b 100644 --- a/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c +++ b/Demos/Host/ClassDriver/MassStorageHost/MassStorageHost.c @@ -84,7 +84,7 @@ int main(void) if (MS_Host_ConfigurePipes(&FlashDisk_MS_Interface, ConfigDescriptorSize, ConfigDescriptorData) != MS_ENUMERROR_NoError) { - printf("Attached Device Not a Valid Mouse.\r\n"); + printf("Attached Device Not a Valid Mass Storage Device.\r\n"); LEDs_SetAllLEDs(LEDMASK_USB_ERROR); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -113,6 +113,8 @@ int main(void) break; } + printf("Total LUNs: %d - Using first LUN in device.\r\n", (MaxLUNIndex + 1)); + if (MS_Host_ResetMSInterface(&FlashDisk_MS_Interface)) { printf("Error resetting Mass Storage interface.\r\n"); diff --git a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c index d0518df1f0..1deefbcb6f 100644 --- a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c +++ b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c @@ -51,32 +51,28 @@ #include "MassStoreCommands.h" /* Globals: */ -/** Current CBW to send to the device. This is automatically filled by the routines - * in this file and is not externally accessible. - */ -static CommandBlockWrapper_t SCSICommandBlock; - -/** Current CSW received from the device. This is automatically filled by the routines - * in this file and is externally accessible so that the return codes may be checked. - */ -CommandStatusWrapper_t SCSICommandStatus; - /** Current Tag value used in issued CBWs to the device. This is automatically incremented - * by the routines in this file, and is not externally accessible. + * each time a command is sent, and is not externally accessible. */ -static uint32_t MassStore_Tag = 1; +static uint32_t MassStore_Tag = 1; /** Routine to send the current CBW to the device, and increment the Tag value as needed. + * + * \param[in] SCSICommandBlock Pointer to a SCSI command block structure to send to the attached device + * \param[in,out] BufferPtr Pointer to a buffer for the data to send or receive to/from the device, or NULL if no data * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ -static uint8_t MassStore_SendCommand(void) +static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; - /* Each transmission should have a unique tag value, excluding values 0 and 0xFFFFFFFF */ - if (++MassStore_Tag == 0xFFFFFFFF) + /* Each transmission should have a unique tag value, increment before use */ + SCSICommandBlock->Tag = ++MassStore_Tag; + + /* Wrap Tag value when invalid - MS class defines tag values of 0 and 0xFFFFFFFF to be invalid */ + if (MassStore_Tag == 0xFFFFFFFF) MassStore_Tag = 1; /* Select the OUT data pipe for CBW transmission */ @@ -84,19 +80,27 @@ static uint8_t MassStore_SendCommand(void) Pipe_Unfreeze(); /* Write the CBW command to the OUT pipe */ - if ((ErrorCode = Pipe_Write_Stream_LE(&SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError) + if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Send the data in the OUT pipe to the attached device */ Pipe_ClearOUT(); /* Wait until command has been sent */ - while(!(Pipe_IsOUTReady())); + Pipe_WaitUntilReady(); /* Freeze pipe after use */ Pipe_Freeze(); - return PIPE_RWSTREAM_NoError; + /* Send data if any */ + if ((BufferPtr != NULL) && + ((ErrorCode = MassStore_SendReceiveData(SCSICommandBlock, BufferPtr)) != PIPE_READYWAIT_NoError)) + { + Pipe_Freeze(); + return ErrorCode; + } + + return ErrorCode; } /** Waits until the attached device is ready to accept data following a CBW, checking @@ -170,18 +174,23 @@ static uint8_t MassStore_WaitForDataReceived(void) /** Sends or receives the transaction's data stage to or from the attached device, reading or * writing to the nominated buffer. * - * \param[in,out] BufferPtr Pointer to the data buffer to read from or write to + * \param[in] SCSICommandBlock Pointer to a SCSI command block structure being sent to the attached device + * \param[in,out] BufferPtr Pointer to the data buffer to read from or write to * * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum */ -static uint8_t MassStore_SendReceiveData(void* BufferPtr) +static uint8_t MassStore_SendReceiveData(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; - uint16_t BytesRem = SCSICommandBlock.Header.DataTransferLength; + uint16_t BytesRem = SCSICommandBlock->DataTransferLength; /* Check the direction of the SCSI command data stage */ - if (SCSICommandBlock.Header.Flags & COMMAND_DIRECTION_DATA_IN) + if (SCSICommandBlock->Flags & COMMAND_DIRECTION_DATA_IN) { + /* Wait until the device has replied with some data */ + if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) + return ErrorCode; + /* Select the IN data pipe for data reception */ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE); Pipe_Unfreeze(); @@ -221,9 +230,11 @@ static uint8_t MassStore_SendReceiveData(void* BufferPtr) /** Routine to receive the current CSW from the device. * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \param[out] SCSICommandStatus Pointer to a destination where the returned status data should be stored + * + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ -static uint8_t MassStore_GetReturnedStatus(void) +static uint8_t MassStore_GetReturnedStatus(CommandStatusWrapper_t* SCSICommandStatus) { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; @@ -236,7 +247,7 @@ static uint8_t MassStore_GetReturnedStatus(void) Pipe_Unfreeze(); /* Load in the CSW from the attached device */ - if ((ErrorCode = Pipe_Read_Stream_LE(&SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError) + if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError) return ErrorCode; /* Clear the data ready for next reception */ @@ -245,13 +256,17 @@ static uint8_t MassStore_GetReturnedStatus(void) /* Freeze the IN pipe after use */ Pipe_Freeze(); - return PIPE_RWSTREAM_NoError; + /* Check to see if command failed */ + if (SCSICommandStatus->Status != Command_Pass) + ErrorCode = MASS_STORE_SCSI_COMMAND_FAILED; + + return ErrorCode; } /** Issues a Mass Storage class specific request to reset the attached device's Mass Storage interface, * readying the device for the next CBW. * - * \return A value from the USB_Host_SendControlErrorCodes_t enum + * \return A value from the USB_Host_SendControlErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_MassStorageReset(void) { @@ -275,7 +290,7 @@ uint8_t MassStore_MassStorageReset(void) * * \param[out] MaxLUNIndex Pointer to the location that the maximum LUN index value should be stored * - * \return A value from the USB_Host_SendControlErrorCodes_t enum + * \return A value from the USB_Host_SendControlErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex) { @@ -311,26 +326,21 @@ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex) * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to * \param[out] InquiryPtr Pointer to the inquiry data structure where the inquiry data from the device is to be stored * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ -uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* const InquiryPtr) +uint8_t MassStore_Inquiry(const uint8_t LUNIndex, SCSI_Inquiry_Response_t* const InquiryPtr) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to issue INQUIRY command */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = sizeof(SCSI_Inquiry_Response_t), - .Flags = COMMAND_DIRECTION_DATA_IN, - .LUN = LUNIndex, - .SCSICommandLength = 6 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = sizeof(SCSI_Inquiry_Response_t), + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 6, + .SCSICommandData = { SCSI_CMD_INQUIRY, 0x00, // Reserved @@ -341,31 +351,23 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Wait until data received from the device */ - if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, InquiryPtr)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - /* Read the returned sense data into the buffer */ - if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)InquiryPtr)) != PIPE_RWSTREAM_NoError) - { - Pipe_Freeze(); - return ReturnCode; - } - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - return PIPE_RWSTREAM_NoError; + + return ErrorCode; } /** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This @@ -374,25 +376,20 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to * \param[out] SensePtr Pointer to the sense data structure where the sense data from the device is to be stored * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ -uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr) +uint8_t MassStore_RequestSense(const uint8_t LUNIndex, SCSI_Request_Sense_Response_t* const SensePtr) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to issue REQUEST SENSE command */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t), - .Flags = COMMAND_DIRECTION_DATA_IN, - .LUN = LUNIndex, - .SCSICommandLength = 6 - }, - + .Signature = CBW_SIGNATURE, + .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t), + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 6, .SCSICommandData = { SCSI_CMD_REQUEST_SENSE, @@ -404,31 +401,23 @@ uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_ } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Wait until data received from the device */ - if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, SensePtr)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - /* Read the returned sense data into the buffer */ - if ((ReturnCode = MassStore_SendReceiveData((uint8_t*)SensePtr)) != PIPE_RWSTREAM_NoError) - { - Pipe_Freeze(); - return ReturnCode; - } - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - return PIPE_RWSTREAM_NoError; + + return ErrorCode; } /** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the @@ -440,27 +429,22 @@ uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_ * \param[in] BlockSize Size in bytes of each block to read * \param[out] BufferPtr Pointer to the buffer where the read data is to be written to * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to read in the given blocks from the device */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = ((uint32_t)Blocks * BlockSize), - .Flags = COMMAND_DIRECTION_DATA_IN, - .LUN = LUNIndex, - .SCSICommandLength = 10 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = ((uint32_t)Blocks * BlockSize), + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 10, + .SCSICommandData = { SCSI_CMD_READ_10, 0x00, // Unused (control bits, all off) @@ -475,31 +459,23 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAd } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Wait until data received from the device */ - if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - /* Read the returned block data into the buffer */ - if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError) - { - Pipe_Freeze(); - return ReturnCode; - } - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - return PIPE_RWSTREAM_NoError; + + return ErrorCode; } /** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the @@ -511,27 +487,22 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAd * \param[in] BlockSize Size in bytes of each block to write * \param[in] BufferPtr Pointer to the buffer where the write data is to be sourced from * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to write the given blocks to the device */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = ((uint32_t)Blocks * BlockSize), - .Flags = COMMAND_DIRECTION_DATA_OUT, - .LUN = LUNIndex, - .SCSICommandLength = 10 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = ((uint32_t)Blocks * BlockSize), + .Flags = COMMAND_DIRECTION_DATA_OUT, + .LUN = LUNIndex, + .SCSICommandLength = 10, + .SCSICommandData = { SCSI_CMD_WRITE_10, 0x00, // Unused (control bits, all off) @@ -546,24 +517,23 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockA } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Write the data to the device from the buffer */ - if ((ReturnCode = MassStore_SendReceiveData(BufferPtr)) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; - } + return ErrorCode; + } - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - return PIPE_RWSTREAM_NoError; + + return ErrorCode; } /** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept @@ -571,26 +541,21 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockA * * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to issue TEST UNIT READY command */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = 0, - .Flags = COMMAND_DIRECTION_DATA_IN, - .LUN = LUNIndex, - .SCSICommandLength = 6 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = 0, + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 6, + .SCSICommandData = { SCSI_CMD_TEST_UNIT_READY, 0x00, // Reserved @@ -601,17 +566,23 @@ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex) } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - return PIPE_RWSTREAM_NoError; + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + { + Pipe_Freeze(); + return ErrorCode; + } + + return ErrorCode; } /** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the @@ -620,26 +591,21 @@ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex) * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to * \param[out] CapacityPtr Device capacity structure where the capacity data is to be stored * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const CapacityPtr) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to issue READ CAPACITY command */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = sizeof(SCSI_Capacity_t), - .Flags = COMMAND_DIRECTION_DATA_IN, - .LUN = LUNIndex, - .SCSICommandLength = 10 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = sizeof(SCSI_Capacity_t), + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 10, + .SCSICommandData = { SCSI_CMD_READ_CAPACITY_10, 0x00, // Reserved @@ -654,35 +620,27 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const Ca } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Wait until data received from the device */ - if ((ReturnCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, CapacityPtr)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; - } - - /* Read the returned capacity data into the buffer */ - if ((ReturnCode = MassStore_SendReceiveData(CapacityPtr)) != PIPE_RWSTREAM_NoError) - { - Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } /* Endian-correct the read data */ CapacityPtr->Blocks = SwapEndian_32(CapacityPtr->Blocks); CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize); - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus()) != PIPE_RWSTREAM_NoError) + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - - return PIPE_RWSTREAM_NoError; + + return ErrorCode; } /** Issues a SCSI Device Prevent/Allow Medium Removal command to the attached device, to lock the physical media from @@ -692,26 +650,21 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex, SCSI_Capacity_t* const Ca * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to * \param[in] PreventRemoval Whether or not the LUN media should be locked to prevent removal or not * - * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum + * \return A value from the Pipe_Stream_RW_ErrorCodes_t enum, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails */ uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool PreventRemoval) { - uint8_t ReturnCode = PIPE_RWSTREAM_NoError; + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; /* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */ - SCSICommandBlock = (CommandBlockWrapper_t) + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) { - .Header = - { - .Signature = CBW_SIGNATURE, - .Tag = MassStore_Tag, - .DataTransferLength = 0, - .Flags = COMMAND_DIRECTION_DATA_OUT, - .LUN = LUNIndex, - .SCSICommandLength = 6 - }, - - .SCSICommandData = + .Signature = CBW_SIGNATURE, + .DataTransferLength = 0, + .Flags = COMMAND_DIRECTION_DATA_OUT, + .LUN = LUNIndex, + .SCSICommandLength = 6, + .SCSICommandData = { SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL, 0x00, // Reserved @@ -722,15 +675,21 @@ uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex, const bool P } }; - /* Send SCSI command to the attached device */ - MassStore_SendCommand(); + CommandStatusWrapper_t SCSICommandStatus; - /* Read in the returned CSW from the device */ - if ((ReturnCode = MassStore_GetReturnedStatus())) + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != PIPE_RWSTREAM_NoError) { Pipe_Freeze(); - return ReturnCode; + return ErrorCode; } - return PIPE_RWSTREAM_NoError; + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + { + Pipe_Freeze(); + return ErrorCode; + } + + return ErrorCode; } diff --git a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.h b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.h index f13b4b15af..1a2e10df3b 100644 --- a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.h +++ b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.h @@ -46,31 +46,34 @@ /* Macros: */ /** Class specific request to reset the Mass Storage interface of the attached device */ - #define REQ_MassStorageReset 0xFF + #define REQ_MassStorageReset 0xFF /** Class specific request to retrieve the maximum Logical Unit Number (LUN) index of the attached device */ - #define REQ_GetMaxLUN 0xFE + #define REQ_GetMaxLUN 0xFE /** Command Block Wrapper signature byte, for verification of valid CBW blocks */ - #define CBW_SIGNATURE 0x43425355UL + #define CBW_SIGNATURE 0x43425355UL /** Command Static Wrapper signature byte, for verification of valid CSW blocks */ - #define CSW_SIGNATURE 0x53425355UL + #define CSW_SIGNATURE 0x53425355UL /** Data direction mask for the Flags field of a CBW, indicating Host-to-Device transfer direction */ - #define COMMAND_DIRECTION_DATA_OUT (0 << 7) + #define COMMAND_DIRECTION_DATA_OUT (0 << 7) /** Data direction mask for the Flags field of a CBW, indicating Device-to-Host transfer direction */ - #define COMMAND_DIRECTION_DATA_IN (1 << 7) + #define COMMAND_DIRECTION_DATA_IN (1 << 7) /** Timeout period between the issuing of a CBW to a device, and the reception of the first packet */ - #define COMMAND_DATA_TIMEOUT_MS 2000 + #define COMMAND_DATA_TIMEOUT_MS 2000 /** Pipe number of the Mass Storage data IN pipe */ - #define MASS_STORE_DATA_IN_PIPE 1 + #define MASS_STORE_DATA_IN_PIPE 1 /** Pipe number of the Mass Storage data OUT pipe */ - #define MASS_STORE_DATA_OUT_PIPE 2 + #define MASS_STORE_DATA_OUT_PIPE 2 + + /** Additional error code for Mass Storage functions when a device returns a logical command failure */ + #define MASS_STORE_SCSI_COMMAND_FAILED 0xC0 /* Type defines: */ /** Type define for a Mass Storage class Command Block Wrapper, used to wrap SCSI @@ -78,17 +81,13 @@ */ typedef struct { - struct - { - uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */ - uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW */ - uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */ - uint8_t Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */ - uint8_t LUN; /**< Logical Unit Number the CBW is addressed to in the device */ - uint8_t SCSICommandLength; /**< Length of the SCSI command in the CBW */ - } Header; - - uint8_t SCSICommandData[16]; /**< SCSI command to issue to the device */ + uint32_t Signature; /**< Command block signature, always equal to CBW_SIGNATURE */ + uint32_t Tag; /**< Current CBW tag, to positively associate a CBW with a CSW (filled automatically) */ + uint32_t DataTransferLength; /**< Length of data to transfer, following the CBW */ + uint8_t Flags; /**< Block flags, equal to one of the COMMAND_DIRECTION_DATA_* macros */ + uint8_t LUN; /**< Logical Unit Number the CBW is addressed to in the device */ + uint8_t SCSICommandLength; /**< Length of the SCSI command in the CBW */ + uint8_t SCSICommandData[16]; /**< SCSI command to issue to the device */ } CommandBlockWrapper_t; /** Type define for a Mass Storage class Command Status Wrapper, used to wrap SCSI @@ -183,23 +182,20 @@ Command_Fail = 1, /**< Command failed to complete successfully */ Phase_Error = 2 /**< Phase error while processing the issued command */ }; - - /* External Variables: */ - extern CommandStatusWrapper_t SCSICommandStatus; - + /* Function Prototypes: */ #if defined(INCLUDE_FROM_MASSSTORE_COMMANDS_C) - static uint8_t MassStore_SendCommand(void); + static uint8_t MassStore_SendCommand(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr); static uint8_t MassStore_WaitForDataReceived(void); - static uint8_t MassStore_SendReceiveData(void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1); - static uint8_t MassStore_GetReturnedStatus(void); + static uint8_t MassStore_SendReceiveData(CommandBlockWrapper_t* SCSICommandBlock, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(1); + static uint8_t MassStore_GetReturnedStatus(CommandStatusWrapper_t* SCSICommandStatus) ATTR_NON_NULL_PTR_ARG(1); #endif uint8_t MassStore_MassStorageReset(void); uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex); - uint8_t MassStore_RequestSense(const uint8_t LUNIndex, const SCSI_Request_Sense_Response_t* const SensePtr) + uint8_t MassStore_RequestSense(const uint8_t LUNIndex, SCSI_Request_Sense_Response_t* const SensePtr) ATTR_NON_NULL_PTR_ARG(2); - uint8_t MassStore_Inquiry(const uint8_t LUNIndex, const SCSI_Inquiry_Response_t* const InquiryPtr) + uint8_t MassStore_Inquiry(const uint8_t LUNIndex, SCSI_Inquiry_Response_t* const InquiryPtr) ATTR_NON_NULL_PTR_ARG(2); uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex, const uint32_t BlockAddress, const uint8_t Blocks, const uint16_t BlockSize, void* BufferPtr) ATTR_NON_NULL_PTR_ARG(5); diff --git a/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.c b/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.c index 2b27b120ed..855ce8df37 100644 --- a/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.c +++ b/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.c @@ -182,7 +182,7 @@ void MassStorage_Task(void) /* Send the request, display error and wait for device detach if request fails */ if ((ErrorCode = MassStore_GetMaxLUN(&MassStore_MaxLUNIndex)) != HOST_SENDCONTROL_Successful) { - ShowDiskReadError(PSTR("Get Max LUN"), false, ErrorCode); + ShowDiskReadError(PSTR("Get Max LUN"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -194,7 +194,7 @@ void MassStorage_Task(void) /* Reset the Mass Storage device interface, ready for use */ if ((ErrorCode = MassStore_MassStorageReset()) != HOST_SENDCONTROL_Successful) { - ShowDiskReadError(PSTR("Mass Storage Reset"), false, ErrorCode); + ShowDiskReadError(PSTR("Mass Storage Reset"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -203,16 +203,17 @@ void MassStorage_Task(void) /* Get sense data from the device - many devices will not accept any other commands until the sense data * is read - both on start-up and after a failed command */ SCSI_Request_Sense_Response_t SenseData; - if (((ErrorCode = MassStore_RequestSense(0, &SenseData)) != 0) || (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_RequestSense(0, &SenseData)) != 0) { - ShowDiskReadError(PSTR("Request Sense"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Request Sense"), ErrorCode); + USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } /* Set the prevent removal flag for the device, allowing it to be accessed */ - if (((ErrorCode = MassStore_PreventAllowMediumRemoval(0, true)) != 0) || (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_PreventAllowMediumRemoval(0, true)) != 0) { - ShowDiskReadError(PSTR("Prevent/Allow Medium Removal"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Prevent/Allow Medium Removal"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -220,9 +221,9 @@ void MassStorage_Task(void) /* Get inquiry data from the device */ SCSI_Inquiry_Response_t InquiryData; - if (((ErrorCode = MassStore_Inquiry(0, &InquiryData)) != 0) || (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_Inquiry(0, &InquiryData)) != 0) { - ShowDiskReadError(PSTR("Inquiry"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Inquiry"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -234,23 +235,30 @@ void MassStorage_Task(void) /* Wait until disk ready */ puts_P(PSTR("Waiting until ready..")); - do + for (;;) { Serial_TxByte('.'); - + /* Abort if device removed */ if (USB_HostState == HOST_STATE_Unattached) break; - if ((ErrorCode = MassStore_TestUnitReady(0)) != PIPE_RWSTREAM_NoError) + /* Check to see if the attached device is ready for new commands */ + ErrorCode = MassStore_TestUnitReady(0); + + /* If attached device is ready, abort the loop */ + if (!(ErrorCode)) + break; + + /* If an error othe than a logical command failure (indicating device busy) returned, abort */ + if (ErrorCode != MASS_STORE_SCSI_COMMAND_FAILED) { - ShowDiskReadError(PSTR("Test Unit Ready"), false, ErrorCode); + ShowDiskReadError(PSTR("Test Unit Ready"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; } } - while (SCSICommandStatus.Status != Command_Pass); puts_P(PSTR("\r\nRetrieving Capacity... ")); @@ -258,9 +266,9 @@ void MassStorage_Task(void) SCSI_Capacity_t DiskCapacity; /* Retrieve disk capacity */ - if (((ErrorCode = MassStore_ReadCapacity(0, &DiskCapacity)) != 0) || (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_ReadCapacity(0, &DiskCapacity)) != 0) { - ShowDiskReadError(PSTR("Read Capacity"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Read Capacity"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -273,10 +281,9 @@ void MassStorage_Task(void) uint8_t BlockBuffer[DiskCapacity.BlockSize]; /* Read in the first 512 byte block from the device */ - if (((ErrorCode = MassStore_ReadDeviceBlock(0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) || - (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_ReadDeviceBlock(0, 0x00000000, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) { - ShowDiskReadError(PSTR("Read Device Block"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Read Device Block"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -320,15 +327,18 @@ void MassStorage_Task(void) if (USB_HostState == HOST_STATE_Unattached) break; } + + /* Abort if device removed */ + if (USB_HostState == HOST_STATE_Unattached) + break; /* Print out the entire disk contents in ASCII format */ - for (uint32_t CurrBlock = 0; CurrBlock < DiskCapacity.Blocks; CurrBlock++) + for (uint32_t CurrBlockAddress = 0; CurrBlockAddress < DiskCapacity.Blocks; CurrBlockAddress++) { /* Read in the next block of data from the device */ - if (((ErrorCode = MassStore_ReadDeviceBlock(0, CurrBlock, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) || - (SCSICommandStatus.Status != Command_Pass)) + if ((ErrorCode = MassStore_ReadDeviceBlock(0, CurrBlockAddress, 1, DiskCapacity.BlockSize, BlockBuffer)) != 0) { - ShowDiskReadError(PSTR("Read Device Block"), (SCSICommandStatus.Status != Command_Pass), ErrorCode); + ShowDiskReadError(PSTR("Read Device Block"), ErrorCode); USB_HostState = HOST_STATE_WaitForDeviceRemoval; break; @@ -360,17 +370,15 @@ void MassStorage_Task(void) * printing error codes to the serial port and waiting until the device is removed before * continuing. * - * \param[in] CommandString ASCII string located in PROGMEM space indicating what operation failed - * \param[in] FailedAtSCSILayer Indicates if the command failed at the (logical) SCSI layer or at the physical USB layer - * \param[in] ErrorCode Error code of the function which failed to complete successfully + * \param[in] CommandString ASCII string located in PROGMEM space indicating what operation failed + * \param[in] ErrorCode Error code of the function which failed to complete successfully */ -void ShowDiskReadError(char* CommandString, bool FailedAtSCSILayer, uint8_t ErrorCode) +void ShowDiskReadError(char* CommandString, uint8_t ErrorCode) { - if (FailedAtSCSILayer) + if (ErrorCode == MASS_STORE_SCSI_COMMAND_FAILED) { /* Display the error code */ printf_P(PSTR(ESC_FG_RED "SCSI command error (%S).\r\n"), CommandString); - printf_P(PSTR(" -- Status Code: %d" ESC_FG_WHITE), ErrorCode); } else { diff --git a/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.h b/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.h index c071099193..e9f02784cc 100644 --- a/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.h +++ b/Demos/Host/LowLevel/MassStorageHost/MassStorageHost.h @@ -82,6 +82,6 @@ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode, const uint8_t SubErrorCode); void EVENT_USB_Host_DeviceEnumerationComplete(void); - void ShowDiskReadError(char* CommandString, bool FailedAtSCSILayer, uint8_t ErrorCode); + void ShowDiskReadError(char* CommandString, uint8_t ErrorCode); #endif diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c index ba281cfa48..65c49b15c7 100644 --- a/LUFA/Drivers/USB/Class/Host/MassStorage.c +++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c @@ -110,8 +110,10 @@ static uint8_t DComp_NextInterfaceBulkDataEndpoint(void* CurrentDescriptor) { if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint) { - uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor, - USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK); + USB_Descriptor_Endpoint_t* CurrentEndpoint = DESCRIPTOR_PCAST(CurrentDescriptor, + USB_Descriptor_Endpoint_t); + + uint8_t EndpointType = (CurrentEndpoint->Attributes & EP_TYPE_MASK); if ((EndpointType == EP_TYPE_BULK) && (!(Pipe_IsEndpointBound(CurrentEndpoint->EndpointAddress)))) @@ -137,7 +139,7 @@ static uint8_t MS_Host_SendCommand(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, MS_ { uint8_t ErrorCode = PIPE_RWSTREAM_NoError; - SCSICommandBlock->Tag = MSInterfaceInfo->State.TransactionTag++; + SCSICommandBlock->Tag = ++MSInterfaceInfo->State.TransactionTag; if (MSInterfaceInfo->State.TransactionTag == 0xFFFFFFFF) MSInterfaceInfo->State.TransactionTag = 1; diff --git a/LUFA/ManPages/ChangeLog.txt b/LUFA/ManPages/ChangeLog.txt index 261ca4eef7..13cf672caf 100644 --- a/LUFA/ManPages/ChangeLog.txt +++ b/LUFA/ManPages/ChangeLog.txt @@ -28,6 +28,7 @@ * - Added non-null function parameter pointer restrictions to USB Class drivers to improve user code reliability * - Added new "Common" section to the class drivers, to hold all mode-independant definitions for clarity * - Moved SCSI command/sense constants into the Mass Storage Class driver, instead of the user-code + * - Altered the SCSI commands in the LowLevel Mass Storage Host to save on FLASH space by reducing function calls * * Fixed: * - Fixed possible lockup in the CDC device class driver, when the host sends data that is a multiple of the diff --git a/Projects/AVRISP/Lib/V2ProtocolTarget.c b/Projects/AVRISP/Lib/V2ProtocolTarget.c index c36295ea0f..d06f06510e 100644 --- a/Projects/AVRISP/Lib/V2ProtocolTarget.c +++ b/Projects/AVRISP/Lib/V2ProtocolTarget.c @@ -92,8 +92,8 @@ void V2Protocol_ChangeTargetResetLine(bool ResetTarget) } else { - RESET_LINE_PORT &= ~RESET_LINE_MASK; RESET_LINE_DDR &= ~RESET_LINE_MASK; + RESET_LINE_PORT &= ~RESET_LINE_MASK; } }