Fix "grep: Version.h: No such file or directory" error when including the core LUFA...
[pub/USBasp.git] / Demos / Host / LowLevel / MassStorageHost / Lib / MassStoreCommands.c
index 1ab7007..0b9b846 100644 (file)
@@ -1,13 +1,13 @@
 /*
              LUFA Library
-     Copyright (C) Dean Camera, 2010.
+     Copyright (C) Dean Camera, 2013.
 
   dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
+           www.lufa-lib.org
 */
 
 /*
-  Copyright 2010  Dean Camera (dean [at] fourwalledcubicle [dot] com)
+  Copyright 2013  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
@@ -18,7 +18,7 @@
   advertising or publicity pertaining to distribution of the
   software without specific, written prior permission.
 
-  The author disclaim all warranties with regard to this
+  The author disclaims all warranties with regard to this
   software, including all implied warranties of merchantability
   and fitness.  In no event shall the author be liable for any
   special, indirect or consequential damages or any damages
@@ -68,20 +68,24 @@ static uint8_t MassStore_SendCommand(MS_CommandBlockWrapper_t* const SCSICommand
 {
        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();
 
        /* Write the CBW command to the OUT pipe */
-       if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t))) != PIPE_RWSTREAM_NoError)
-         return ErrorCode;
+       if ((ErrorCode = Pipe_Write_Stream_LE(SCSICommandBlock, sizeof(MS_CommandBlockWrapper_t), NULL)) !=
+                                             PIPE_RWSTREAM_NoError)
+       {
+               Pipe_Freeze();
+               return ErrorCode;
+       }
 
        /* Send the data in the OUT pipe to the attached device */
        Pipe_ClearOUT();
@@ -92,15 +96,22 @@ static uint8_t MassStore_SendCommand(MS_CommandBlockWrapper_t* const SCSICommand
        /* 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
@@ -142,7 +153,7 @@ static uint8_t MassStore_WaitForDataReceived(void)
                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;
                }
@@ -155,7 +166,7 @@ static uint8_t MassStore_WaitForDataReceived(void)
                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;
                }
@@ -189,7 +200,7 @@ static uint8_t MassStore_SendReceiveData(MS_CommandBlockWrapper_t* const SCSICom
        uint16_t BytesRem  = SCSICommandBlock->DataTransferLength;
 
        /* Check the direction of the SCSI command data stage */
-       if (SCSICommandBlock->Flags & COMMAND_DIRECTION_DATA_IN)
+       if (SCSICommandBlock->Flags & MS_COMMAND_DIR_DATA_IN)
        {
                /* Wait until the device has replied with some data */
                if ((ErrorCode = MassStore_WaitForDataReceived()) != PIPE_RWSTREAM_NoError)
@@ -200,7 +211,7 @@ static uint8_t MassStore_SendReceiveData(MS_CommandBlockWrapper_t* const SCSICom
                Pipe_Unfreeze();
 
                /* Read in the block data from the pipe */
-               if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)
+               if ((ErrorCode = Pipe_Read_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
                  return ErrorCode;
 
                /* Acknowledge the packet */
@@ -213,7 +224,7 @@ static uint8_t MassStore_SendReceiveData(MS_CommandBlockWrapper_t* const SCSICom
                Pipe_Unfreeze();
 
                /* Write the block data to the pipe */
-               if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem)) != PIPE_RWSTREAM_NoError)
+               if ((ErrorCode = Pipe_Write_Stream_LE(BufferPtr, BytesRem, NULL)) != PIPE_RWSTREAM_NoError)
                  return ErrorCode;
 
                /* Acknowledge the packet */
@@ -251,8 +262,11 @@ static uint8_t MassStore_GetReturnedStatus(MS_CommandStatusWrapper_t* const SCSI
        Pipe_Unfreeze();
 
        /* Load in the CSW from the attached device */
-       if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t))) != PIPE_RWSTREAM_NoError)
-         return ErrorCode;
+       if ((ErrorCode = Pipe_Read_Stream_LE(SCSICommandStatus, sizeof(MS_CommandStatusWrapper_t), NULL)) !=
+                                            PIPE_RWSTREAM_NoError)
+       {
+               return ErrorCode;
+       }
 
        /* Clear the data ready for next reception */
        Pipe_ClearIN();
@@ -268,12 +282,15 @@ static uint8_t MassStore_GetReturnedStatus(MS_CommandStatusWrapper_t* const SCSI
 }
 
 /** 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),
@@ -286,7 +303,22 @@ uint8_t MassStore_MassStorageReset(void)
        /* 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
@@ -302,7 +334,7 @@ uint8_t MassStore_MassStorageReset(void)
  */
 uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)
 {
-       uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
+       uint8_t ErrorCode;
 
        USB_ControlRequest = (USB_Request_Header_t)
                {
@@ -342,14 +374,12 @@ uint8_t MassStore_GetMaxLUN(uint8_t* const MaxLUNIndex)
 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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = sizeof(SCSI_Inquiry_Response_t),
-                       .Flags              = COMMAND_DIRECTION_DATA_IN,
+                       .Flags              = MS_COMMAND_DIR_DATA_IN,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 6,
                        .SCSICommandData    =
@@ -363,23 +393,8 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex,
                                }
                };
 
-       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
@@ -393,14 +408,12 @@ uint8_t MassStore_Inquiry(const uint8_t LUNIndex,
 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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),
-                       .Flags              = COMMAND_DIRECTION_DATA_IN,
+                       .Flags              = MS_COMMAND_DIR_DATA_IN,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 6,
                        .SCSICommandData =
@@ -414,23 +427,8 @@ uint8_t MassStore_RequestSense(const uint8_t LUNIndex,
                                }
                };
 
-       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
@@ -450,14 +448,12 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex,
                                   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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = ((uint32_t)Blocks * BlockSize),
-                       .Flags              = COMMAND_DIRECTION_DATA_IN,
+                       .Flags              = MS_COMMAND_DIR_DATA_IN,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 10,
                        .SCSICommandData    =
@@ -475,23 +471,8 @@ uint8_t MassStore_ReadDeviceBlock(const uint8_t LUNIndex,
                                }
                };
 
-       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
@@ -511,14 +492,12 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex,
                                    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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = ((uint32_t)Blocks * BlockSize),
-                       .Flags              = COMMAND_DIRECTION_DATA_OUT,
+                       .Flags              = MS_COMMAND_DIR_DATA_OUT,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 10,
                        .SCSICommandData    =
@@ -536,23 +515,8 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex,
                                }
                };
 
-       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
@@ -564,14 +528,12 @@ uint8_t MassStore_WriteDeviceBlock(const uint8_t LUNIndex,
  */
 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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = 0,
-                       .Flags              = COMMAND_DIRECTION_DATA_IN,
+                       .Flags              = MS_COMMAND_DIR_DATA_IN,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 6,
                        .SCSICommandData    =
@@ -585,23 +547,8 @@ uint8_t MassStore_TestUnitReady(const uint8_t LUNIndex)
                                }
                };
 
-       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
@@ -620,9 +567,9 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex,
        /* Create a CBW with a SCSI command to issue READ CAPACITY command */
        MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = sizeof(SCSI_Capacity_t),
-                       .Flags              = COMMAND_DIRECTION_DATA_IN,
+                       .Flags              = MS_COMMAND_DIR_DATA_IN,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 10,
                        .SCSICommandData    =
@@ -640,26 +587,14 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex,
                                }
                };
 
-       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;
 }
 
@@ -675,14 +610,12 @@ uint8_t MassStore_ReadCapacity(const uint8_t LUNIndex,
 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)
                {
-                       .Signature          = CBW_SIGNATURE,
+                       .Signature          = MS_CBW_SIGNATURE,
                        .DataTransferLength = 0,
-                       .Flags              = COMMAND_DIRECTION_DATA_OUT,
+                       .Flags              = MS_COMMAND_DIR_DATA_OUT,
                        .LUN                = LUNIndex,
                        .SCSICommandLength  = 6,
                        .SCSICommandData    =
@@ -696,22 +629,7 @@ uint8_t MassStore_PreventAllowMediumRemoval(const uint8_t LUNIndex,
                                }
                };
 
-       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);
 }