/*
LUFA Library
- Copyright (C) Dean Camera, 2011.
+ Copyright (C) Dean Camera, 2012.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2012 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
{
uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
- /* 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)
+ if (++MassStore_Tag == 0xFFFFFFFF)
MassStore_Tag = 1;
+ /* Each transmission should have a unique tag value, increment before use */
+ SCSICommandBlock->Tag = MassStore_Tag;
+
/* Select the OUT data pipe for CBW transmission */
Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);
Pipe_Unfreeze();
if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t), NULL)) !=
PIPE_RWSTREAM_NoError)
{
+ Pipe_Freeze();
return ErrorCode;
}
/* Freeze pipe after use */
Pipe_Freeze();
- /* Send data if any */
- if ((BufferPtr != NULL) &&
- ((ErrorCode = MassStore_SendReceiveData(SCSICommandBlock, BufferPtr)) != PIPE_READYWAIT_NoError))
+ if (BufferPtr != NULL)
{
- Pipe_Freeze();
- return ErrorCode;
+ /* Transfer the requested data (if any) to or from the device */
+ ErrorCode = MassStore_SendReceiveData(SCSICommandBlock, (void*)BufferPtr);
+
+ /* Only fail completely if the transfer fails without a STALL, as a logical STALL can be recovered from */
+ if ((ErrorCode != PIPE_RWSTREAM_NoError) && (ErrorCode != PIPE_RWSTREAM_PipeStalled))
+ {
+ Pipe_Freeze();
+ return ErrorCode;
+ }
}
- return ErrorCode;
+ /* Retrieve the returned SCSI status from the device */
+ MS_CommandStatusWrapper_t SCSIStatusBlock;
+ return MassStore_GetReturnedStatus(&SCSIStatusBlock);
}
/** Waits until the attached device is ready to accept data following a CBW, checking
if (Pipe_IsStalled())
{
/* Clear the stall condition on the OUT pipe */
- USB_Host_ClearPipeStall(MASS_STORE_DATA_OUT_PIPE);
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
if (Pipe_IsStalled())
{
/* Clear the stall condition on the IN pipe */
- USB_Host_ClearPipeStall(MASS_STORE_DATA_IN_PIPE);
+ USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
return PIPE_RWSTREAM_PipeStalled;
}
{
return ErrorCode;
}
-
+
/* Clear the data ready for next reception */
Pipe_ClearIN();
}
/** Issues a Mass Storage class specific request to reset the attached device's Mass Storage interface,
- * readying the device for the next CBW.
+ * readying the device for the next CBW. The Data endpoints are cleared of any STALL condition once this
+ * command completes successfully.
*
* \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)
{
+ uint8_t ErrorCode;
+
USB_ControlRequest = (USB_Request_Header_t)
{
.bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
/* Select the control pipe for the request transfer */
Pipe_SelectPipe(PIPE_CONTROLPIPE);
- return USB_Host_SendControlRequest(NULL);
+ if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ /* Select first data pipe to clear STALL condition if one exists */
+ Pipe_SelectPipe(MASS_STORE_DATA_IN_PIPE);
+
+ if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ /* Select second data pipe to clear STALL condition if one exists */
+ Pipe_SelectPipe(MASS_STORE_DATA_OUT_PIPE);
+
+ if ((ErrorCode = USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress())) != HOST_SENDCONTROL_Successful)
+ return ErrorCode;
+
+ return HOST_SENDCONTROL_Successful;
}
/** Issues a Mass Storage class specific request to determine the index of the highest numbered Logical
*/
uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)
{
- uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
+ uint8_t ErrorCode;
USB_ControlRequest = (USB_Request_Header_t)
{
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 */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_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;
+ return MassStore_SendCommand(&SCSICommandBlock, InquiryPtr);
}
/** Issues a SCSI Request Sense command to the attached device, to determine the current SCSI sense information. This
uint8_t MassStore_RequestSense(const uint8_t LUNIndex,
SCSI_Request_Sense_Response_t* const SensePtr)
{
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
-
/* Create a CBW with a SCSI command to issue REQUEST SENSE command */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
- if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, SensePtr)) != 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;
+ return MassStore_SendCommand(&SCSICommandBlock, SensePtr);
}
/** Issues a SCSI Device Block Read command to the attached device, to read in one or more data blocks from the
const uint16_t BlockSize,
void* BufferPtr)
{
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
-
/* Create a CBW with a SCSI command to read in the given blocks from the device */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
- if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != 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;
+ return MassStore_SendCommand(&SCSICommandBlock, BufferPtr);
}
/** Issues a SCSI Device Block Write command to the attached device, to write one or more data blocks to the
const uint16_t BlockSize,
void* BufferPtr)
{
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
-
/* Create a CBW with a SCSI command to write the given blocks to the device */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
- if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, BufferPtr)) != 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;
+ return MassStore_SendCommand(&SCSICommandBlock, BufferPtr);
}
/** Issues a SCSI Device Test Unit Ready command to the attached device, to determine if the device is ready to accept
*/
uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)
{
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
-
/* Create a CBW with a SCSI command to issue TEST UNIT READY command */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
- if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != 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;
+ return MassStore_SendCommand(&SCSICommandBlock, NULL);
}
/** Issues a SCSI Device Read Capacity command to the attached device, to determine the capacity of the
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, CapacityPtr)) != PIPE_RWSTREAM_NoError)
- {
- Pipe_Freeze();
- return ErrorCode;
- }
+ return ErrorCode;
/* Endian-correct the read data */
CapacityPtr->Blocks = SwapEndian_32(CapacityPtr->Blocks);
CapacityPtr->BlockSize = SwapEndian_32(CapacityPtr->BlockSize);
- /* Retrieve status information from the attached device */
- if ((ErrorCode = MassStore_GetReturnedStatus(&SCSICommandStatus)) != PIPE_RWSTREAM_NoError)
- {
- Pipe_Freeze();
- return ErrorCode;
- }
-
return ErrorCode;
}
uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex,
const bool PreventRemoval)
{
- uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
-
/* Create a CBW with a SCSI command to issue PREVENT ALLOW MEDIUM REMOVAL command */
MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
{
}
};
- MS_CommandStatusWrapper_t SCSICommandStatus;
-
/* Send the command and any data to the attached device */
- if ((ErrorCode = MassStore_SendCommand(&SCSICommandBlock, NULL)) != 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;
+ return MassStore_SendCommand(&SCSICommandBlock, NULL);
}