X-Git-Url: http://git.linex4red.de/pub/USBasp.git/blobdiff_plain/34f6e0dd33230441b8a91130467b3164e343853e..a9e0935a90346beb0c981924becc1f55d969a08b:/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c diff --git a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c index afeace02f..be92d69c1 100644 --- a/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c +++ b/Demos/Host/LowLevel/MassStorageHost/Lib/MassStoreCommands.c @@ -1,21 +1,21 @@ /* LUFA Library - Copyright (C) Dean Camera, 2009. + Copyright (C) Dean Camera, 2010. dean [at] fourwalledcubicle [dot] com www.fourwalledcubicle.com */ /* - Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, and distribute this software - and its documentation for any purpose and without fee is hereby - granted, provided that the above copyright notice appear in all - copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the + Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the software without specific, written prior permission. The author disclaim all warranties with regard to this @@ -50,33 +50,28 @@ #define INCLUDE_FROM_MASSSTORE_COMMANDS_C #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,18 +79,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(); - while(!(Pipe_IsOUTReady())); + /* Wait until command has been sent */ + 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 @@ -134,7 +138,7 @@ static uint8_t MassStore_WaitForDataReceived(void) if (Pipe_IsStalled()) { /* Clear the stall condition on the OUT pipe */ - MassStore_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); + USB_Host_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE); return PIPE_RWSTREAM_PipeStalled; } @@ -147,13 +151,13 @@ static uint8_t MassStore_WaitForDataReceived(void) if (Pipe_IsStalled()) { /* Clear the stall condition on the IN pipe */ - MassStore_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); + USB_Host_ClearPipeStall(MASS_STORE_DATA_IN_PIPE); return PIPE_RWSTREAM_PipeStalled; } /* Check to see if the device was disconnected, if so exit function */ - if (!(USB_IsConnected)) + if (USB_HostState == HOST_STATE_Unattached) return PIPE_RWSTREAM_DeviceDisconnected; }; @@ -169,18 +173,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 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(); @@ -205,7 +214,11 @@ static uint8_t MassStore_SendReceiveData(void* BufferPtr) /* Acknowledge the packet */ Pipe_ClearOUT(); - while (!(Pipe_IsOUTReady())); + while (!(Pipe_IsOUTReady())) + { + if (USB_HostState == HOST_STATE_Unattached) + return PIPE_RWSTREAM_DeviceDisconnected; + } } /* Freeze used pipe after use */ @@ -216,13 +229,15 @@ 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; - /* If an error in the command ocurred, abort */ + /* If an error in the command occurred, abort */ if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError) return ErrorCode; @@ -231,7 +246,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 */ @@ -240,36 +255,17 @@ static uint8_t MassStore_GetReturnedStatus(void) /* Freeze the IN pipe after use */ Pipe_Freeze(); - return PIPE_RWSTREAM_NoError; -} - -/** Clears the stall condition in the attached device on the nominated endpoint number. - * - * \param EndpointNum Endpoint number in the attached device whose stall condition is to be cleared - * - * \return A value from the USB_Host_SendControlErrorCodes_t enum - */ -uint8_t MassStore_ClearPipeStall(const uint8_t EndpointNum) -{ - USB_ControlRequest = (USB_Request_Header_t) - { - .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_ENDPOINT), - .bRequest = REQ_ClearFeature, - .wValue = FEATURE_ENDPOINT_HALT, - .wIndex = EndpointNum, - .wLength = 0, - }; + /* Check to see if command failed */ + if (SCSICommandStatus->Status != Command_Pass) + ErrorCode = MASS_STORE_SCSI_COMMAND_FAILED; - /* Select the control pipe for the request transfer */ - Pipe_SelectPipe(PIPE_CONTROLPIPE); - - return USB_Host_SendControlRequest(NULL); + 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) { @@ -291,13 +287,17 @@ uint8_t MassStore_MassStorageReset(void) /** Issues a Mass Storage class specific request to determine the index of the highest numbered Logical * Unit in the attached device. * - * \param MaxLUNIndex Pointer to the location that the maximum LUN index value should be stored + * \note Some devices do not support this request, and will STALL it when issued. To get around this, + * on unsupported devices the max LUN index will be reported as zero and no error will be returned + * if the device STALLs the request. + * + * \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) { - uint8_t ErrorCode; + uint8_t ErrorCode = HOST_SENDCONTROL_Successful; USB_ControlRequest = (USB_Request_Header_t) { @@ -317,37 +317,85 @@ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex) Pipe_ClearStall(); /* Some faulty Mass Storage devices don't implement the GET_MAX_LUN request, so assume a single LUN */ - *MaxLUNIndex = 0; + *MaxLUNIndex = 0; + + /* Clear the error, and pretend the request executed correctly if the device STALLed it */ + ErrorCode = HOST_SENDCONTROL_Successful; } return ErrorCode; } +/** Issues a SCSI Inquiry command to the attached device, to determine the device's information. This + * gives information on the device's capabilities. + * + * \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, or MASS_STORE_SCSI_COMMAND_FAILED if the SCSI command fails + */ +uint8_t MassStore_Inquiry(const uint8_t LUNIndex, SCSI_Inquiry_Response_t* const InquiryPtr) +{ + uint8_t ErrorCode = PIPE_RWSTREAM_NoError; + + /* Create a CBW with a SCSI command to issue INQUIRY command */ + CommandBlockWrapper_t SCSICommandBlock = (CommandBlockWrapper_t) + { + .Signature = CBW_SIGNATURE, + .DataTransferLength = sizeof(SCSI_Inquiry_Response_t), + .Flags = COMMAND_DIRECTION_DATA_IN, + .LUN = LUNIndex, + .SCSICommandLength = 6, + .SCSICommandData = + { + SCSI_CMD_INQUIRY, + 0x00, // Reserved + 0x00, // Reserved + 0x00, // Reserved + sizeof(SCSI_Inquiry_Response_t), // Allocation Length + 0x00 // Unused (control) + } + }; + + CommandStatusWrapper_t SCSICommandStatus; + + /* Send the command and any data to the attached device */ + if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, InquiryPtr)) != PIPE_RWSTREAM_NoError) + { + Pipe_Freeze(); + return ErrorCode; + } + + /* Retrieve status information from the attached device */ + if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError) + { + Pipe_Freeze(); + return ErrorCode; + } + + return ErrorCode; +} + /** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This * gives error codes for the last issued SCSI command to the device. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to - * \param SensePtr Pointer to the sense data structure where the sense data from the device is to be stored + * \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, @@ -359,63 +407,50 @@ 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 * storage medium into a buffer. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to - * \param BlockAddress Start block address to read from - * \param Blocks Number of blocks to read from the device - * \param BlockSize Size in bytes of each block to read - * \param BufferPtr Pointer to the buffer where the read data is to be written to + * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to + * \param[in] BlockAddress Start block address to read from + * \param[in] Blocks Number of blocks to read from the device + * \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) @@ -430,63 +465,50 @@ 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 * storage medium from a buffer. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to - * \param BlockAddress Start block address to write to - * \param Blocks Number of blocks to write to in the device - * \param BlockSize Size in bytes of each block to write - * \param BufferPtr Pointer to the buffer where the write data is to be sourced from + * \param[in] LUNIndex Index of the LUN inside the device the command is being addressed to + * \param[in] BlockAddress Start block address to write to + * \param[in] Blocks Number of blocks to write to in the device + * \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) @@ -501,51 +523,45 @@ 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 * other commands. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to + * \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 @@ -556,45 +572,46 @@ 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 * given Logical Unit within the device. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to - * \param CapacityPtr Device capacity structure where the capacity data is to be stored + * \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 @@ -609,64 +626,51 @@ 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 * being removed. This is a legacy command for SCSI disks with removable storage (such as ZIP disks), but should still * be issued before the first read or write command is sent. * - * \param LUNIndex Index of the LUN inside the device the command is being addressed to - * \param PreventRemoval Whether or not the LUN media should be locked to prevent removal or not + * \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 @@ -677,15 +681,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; }