Fixed MassStorage based demos and projects resetting the SCSI sense values before...
authorDean Camera <dean@fourwalledcubicle.com>
Wed, 18 Aug 2010 10:33:21 +0000 (10:33 +0000)
committerDean Camera <dean@fourwalledcubicle.com>
Wed, 18 Aug 2010 10:33:21 +0000 (10:33 +0000)
Added missing DataflashManager_CheckDataflashOperation() function to the MassStorageKeyboard demo, removed redundant SCSI_Codes.h file as these values are part of the MassStorage Class Driver.

17 files changed:
Demos/Device/ClassDriver/MassStorage/Lib/SCSI.c
Demos/Device/ClassDriver/MassStorage/Lib/SCSI.h
Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.c
Demos/Device/ClassDriver/MassStorageKeyboard/Lib/DataflashManager.h
Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.c
Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI.h
Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h [deleted file]
Demos/Device/LowLevel/MassStorage/Lib/SCSI.c
Demos/Device/LowLevel/MassStorage/Lib/SCSI.h
LUFA/DriverStubs/Dataflash.h
LUFA/ManPages/ChangeLog.txt
Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.c
Projects/Incomplete/StandaloneProgrammer/Lib/SCSI.h
Projects/TempDataLogger/Lib/SCSI.c
Projects/TempDataLogger/Lib/SCSI.h
Projects/Webserver/Lib/SCSI.c
Projects/Webserver/Lib/SCSI.h

index 4efbbc0..fed57f7 100644 (file)
@@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData =
  *  a command failure due to a ILLEGAL REQUEST.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
-       /* Set initial sense data, before the requested command is processed */
-       SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
-                      SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                      SCSI_ASENSEQ_NO_QUALIFIER);
-                                          
+       bool CommandSuccess = false;
+
        /* Run the appropriate SCSI command hander function based on the passed command */
        switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
        {
                case SCSI_CMD_INQUIRY:
-                       SCSI_Command_Inquiry(MSInterfaceInfo);                  
+                       CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);                 
                        break;
                case SCSI_CMD_REQUEST_SENSE:
-                       SCSI_Command_Request_Sense(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
-                       SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                 
+                       CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                        
                        break;
                case SCSI_CMD_SEND_DIAGNOSTIC:
-                       SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
                        break;
                case SCSI_CMD_WRITE_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
                case SCSI_CMD_READ_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
                        break;
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                        /* These commands should just succeed, no handling required */
+                       CommandSuccess = true;
                        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
                        break;
                default:
@@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                        break;
        }
 
-       return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
+       /* Check if command was successfully processed */
+       if (CommandSuccess)
+       {
+               SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+                              SCSI_ASENSEQ_NO_QUALIFIER);
+               
+               return true;
+       }
+
+       return false;
 }
 
 /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
  *  and capabilities to the host.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint16_t AllocationLength  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
        uint16_t BytesTransferred  = (AllocationLength < sizeof(InquiryData))? AllocationLength :
@@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
@@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
  *  including the error code and additional error information so that the host can determine why a command failed to complete.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint8_t  AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
        uint8_t  BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
@@ -181,19 +197,23 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf
        uint8_t PadBytes[AllocationLength - BytesTransferred];
 
        Endpoint_Write_Stream_LE(&SenseData, BytesTransferred, NO_STREAM_CALLBACK);
-       Endpoint_Write_Stream_LE(&PadBytes, (AllocationLength - BytesTransferred), NO_STREAM_CALLBACK);
+       Endpoint_Write_Stream_LE(&PadBytes, sizeof(PadBytes), NO_STREAM_CALLBACK);
        Endpoint_ClearIN();
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+       return true;
 }
 
 /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
  *  on the selected Logical Unit (drive), as a number of OS-sized blocks.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint32_t LastBlockAddressInLUN = (LUN_MEDIA_BLOCKS - 1);
        uint32_t MediaBlockSize        = VIRTUAL_MEMORY_BLOCK_SIZE;
@@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
@@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
  *  supported.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        /* Check to see if the SELF TEST bit is not set */
        if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
@@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Check to see if all attached Dataflash ICs are functional */
@@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
                               SCSI_ASENSEQ_NO_QUALIFIER);      
        
-               return;
+               return false;
        }
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
@@ -246,12 +272,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
-       uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
-       uint16_t TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
+       uint32_t BlockAddress;
+       uint16_t TotalBlocks;
+       
+       /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
+       BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
+
+       /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
+       TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
        
        /* Check if the block address is outside the maximum allowable value for the LUN */
        if (BlockAddress >= LUN_MEDIA_BLOCKS)
@@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
                               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
 
        #if (TOTAL_LUNS > 1)
@@ -277,4 +311,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+       
+       return true;
 }
index 0c00cfb..44ccb98 100644 (file)
@@ -56,9 +56,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = (key);                   \
-                                                                  SenseData.AdditionalSenseCode = (acode);      \
-                                                                  SenseData.AdditionalSenseQualifier = (aqual); }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
                bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
                
                #if defined(INCLUDE_FROM_SCSI_C)
-                       static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+                       static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                                              const bool IsDataRead);
                #endif
                
index 445082f..ce2ac81 100644 (file)
@@ -498,3 +498,36 @@ void DataflashManager_ResetDataflashProtections(void)
        /* Deselect current Dataflash chip */
        Dataflash_DeselectChip();
 }
+
+/** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.
+ *
+ *  \return Boolean true if all media chips are working, false otherwise
+ */
+bool DataflashManager_CheckDataflashOperation(void)
+{
+       uint8_t ReturnByte;
+
+       /* Test first Dataflash IC is present and responding to commands */
+       Dataflash_SelectChip(DATAFLASH_CHIP1);
+       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
+       ReturnByte = Dataflash_ReceiveByte();
+       Dataflash_DeselectChip();
+
+       /* If returned data is invalid, fail the command */
+       if (ReturnByte != DF_MANUFACTURER_ATMEL)
+         return false;
+
+       #if (DATAFLASH_TOTALCHIPS == 2)
+       /* Test second Dataflash IC is present and responding to commands */
+       Dataflash_SelectChip(DATAFLASH_CHIP2);
+       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
+       ReturnByte = Dataflash_ReceiveByte();
+       Dataflash_DeselectChip();
+
+       /* If returned data is invalid, fail the command */
+       if (ReturnByte != DF_MANUFACTURER_ATMEL)
+         return false;
+       #endif
+       
+       return true;
+}
index 694867f..d5a9fd5 100644 (file)
@@ -83,5 +83,6 @@
                                                     uint16_t TotalBlocks,
                                                     uint8_t* BufferPtr) ATTR_NON_NULL_PTR_ARG(3);
                void DataflashManager_ResetDataflashProtections(void);
+               bool DataflashManager_CheckDataflashOperation(void);
                
 #endif
index 0dac650..fed57f7 100644 (file)
@@ -85,6 +85,8 @@ SCSI_Request_Sense_Response_t SenseData =
  *  a command failure due to a ILLEGAL REQUEST.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
@@ -236,8 +238,6 @@ static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
  */
 static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
-       uint8_t ReturnByte;
-
        /* Check to see if the SELF TEST bit is not set */
        if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
        {
@@ -249,32 +249,8 @@ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                return false;
        }
        
-       /* Test first Dataflash IC is present and responding to commands */
-       Dataflash_SelectChip(DATAFLASH_CHIP1);
-       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
-       ReturnByte = Dataflash_ReceiveByte();
-       Dataflash_DeselectChip();
-
-       /* If returned data is invalid, fail the command */
-       if (ReturnByte != DF_MANUFACTURER_ATMEL)
-       {
-               /* Update SENSE key with a hardware error condition and return command fail */
-               SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
-                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                              SCSI_ASENSEQ_NO_QUALIFIER);      
-       
-               return false;
-       }
-
-       #if (DATAFLASH_TOTALCHIPS == 2)
-       /* Test second Dataflash IC is present and responding to commands */
-       Dataflash_SelectChip(DATAFLASH_CHIP2);
-       Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
-       ReturnByte = Dataflash_ReceiveByte();
-       Dataflash_DeselectChip();
-
-       /* If returned data is invalid, fail the command */
-       if (ReturnByte != DF_MANUFACTURER_ATMEL)
+       /* Check to see if all attached Dataflash ICs are functional */
+       if (!(DataflashManager_CheckDataflashOperation()))
        {
                /* Update SENSE key with a hardware error condition and return command fail */
                SCSI_SET_SENSE(SCSI_SENSE_KEY_HARDWARE_ERROR,
@@ -283,7 +259,6 @@ static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
        
                return false;
        }
-       #endif
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
index 6025d86..96489ab 100644 (file)
@@ -46,7 +46,6 @@
                #include "MassStorageKeyboard.h"
                #include "Descriptors.h"
                #include "DataflashManager.h"
-               #include "SCSI_Codes.h"
        
        /* Macros: */
                /** Macro to set the current SCSI sense data to the given key, additional sense code and additional sense qualifier. This
@@ -57,9 +56,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = key;              \
-                                                                  SenseData.AdditionalSenseCode = acode; \
-                                                                  SenseData.AdditionalSenseQualifier = aqual; }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
diff --git a/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h b/Demos/Device/ClassDriver/MassStorageKeyboard/Lib/SCSI_Codes.h
deleted file mode 100644 (file)
index 5b6b76a..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-             LUFA Library
-     Copyright (C) Dean Camera, 2010.
-              
-  dean [at] fourwalledcubicle [dot] com
-      www.fourwalledcubicle.com
-*/
-
-/*
-  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
-  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
-  whatsoever resulting from loss of use, data or profits, whether
-  in an action of contract, negligence or other tortious action,
-  arising out of or in connection with the use or performance of
-  this software.
-*/
-
-/** \file
- *
- *  Header containing macros for possible SCSI commands and SENSE data. Refer to
- *  the SCSI standard documentation for more information on each SCSI command and
- *  the SENSE data.
- */
-#ifndef _SCSI_CODES_H_
-#define _SCSI_CODES_H_
-
-       /* Macros: */
-               #define SCSI_CMD_INQUIRY                               0x12
-               #define SCSI_CMD_REQUEST_SENSE                         0x03
-               #define SCSI_CMD_TEST_UNIT_READY                       0x00
-               #define SCSI_CMD_READ_CAPACITY_10                      0x25
-               #define SCSI_CMD_SEND_DIAGNOSTIC                       0x1D
-               #define SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL          0x1E
-               #define SCSI_CMD_WRITE_10                              0x2A
-               #define SCSI_CMD_READ_10                               0x28
-               #define SCSI_CMD_WRITE_6                               0x0A
-               #define SCSI_CMD_READ_6                                0x08
-               #define SCSI_CMD_VERIFY_10                             0x2F
-               #define SCSI_CMD_MODE_SENSE_6                          0x1A
-               #define SCSI_CMD_MODE_SENSE_10                         0x5A
-
-               #define SCSI_SENSE_KEY_GOOD                            0x00
-               #define SCSI_SENSE_KEY_RECOVERED_ERROR                 0x01
-               #define SCSI_SENSE_KEY_NOT_READY                       0x02
-               #define SCSI_SENSE_KEY_MEDIUM_ERROR                    0x03
-               #define SCSI_SENSE_KEY_HARDWARE_ERROR                  0x04
-               #define SCSI_SENSE_KEY_ILLEGAL_REQUEST                 0x05
-               #define SCSI_SENSE_KEY_UNIT_ATTENTION                  0x06
-               #define SCSI_SENSE_KEY_DATA_PROTECT                    0x07
-               #define SCSI_SENSE_KEY_BLANK_CHECK                     0x08
-               #define SCSI_SENSE_KEY_VENDOR_SPECIFIC                 0x09
-               #define SCSI_SENSE_KEY_COPY_ABORTED                    0x0A
-               #define SCSI_SENSE_KEY_ABORTED_COMMAND                 0x0B
-               #define SCSI_SENSE_KEY_VOLUME_OVERFLOW                 0x0D
-               #define SCSI_SENSE_KEY_MISCOMPARE                      0x0E
-
-               #define SCSI_ASENSE_NO_ADDITIONAL_INFORMATION          0x00
-               #define SCSI_ASENSE_LOGICAL_UNIT_NOT_READY             0x04
-               #define SCSI_ASENSE_INVALID_FIELD_IN_CDB               0x24
-               #define SCSI_ASENSE_WRITE_PROTECTED                    0x27
-               #define SCSI_ASENSE_FORMAT_ERROR                       0x31
-               #define SCSI_ASENSE_INVALID_COMMAND                    0x20
-               #define SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21
-               #define SCSI_ASENSE_MEDIUM_NOT_PRESENT                 0x3A
-
-               #define SCSI_ASENSEQ_NO_QUALIFIER                      0x00
-               #define SCSI_ASENSEQ_FORMAT_COMMAND_FAILED             0x01
-               #define SCSI_ASENSEQ_INITIALIZING_COMMAND_REQUIRED     0x02
-               #define SCSI_ASENSEQ_OPERATION_IN_PROGRESS             0x07
-
-#endif
index 4d2323e..7600595 100644 (file)
@@ -88,36 +88,34 @@ SCSI_Request_Sense_Response_t SenseData =
  */
 bool SCSI_DecodeSCSICommand(void)
 {
-       /* Set initial sense data, before the requested command is processed */
-       SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
-                      SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                      SCSI_ASENSEQ_NO_QUALIFIER);
+       bool CommandSuccess = false;
 
        /* Run the appropriate SCSI command hander function based on the passed command */
        switch (CommandBlock.SCSICommandData[0])
        {
                case SCSI_CMD_INQUIRY:
-                       SCSI_Command_Inquiry();                 
+                       CommandSuccess = SCSI_Command_Inquiry();                        
                        break;
                case SCSI_CMD_REQUEST_SENSE:
-                       SCSI_Command_Request_Sense();
+                       CommandSuccess = SCSI_Command_Request_Sense();
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
-                       SCSI_Command_Read_Capacity_10();                        
+                       CommandSuccess = SCSI_Command_Read_Capacity_10();                       
                        break;
                case SCSI_CMD_SEND_DIAGNOSTIC:
-                       SCSI_Command_Send_Diagnostic();
+                       CommandSuccess = SCSI_Command_Send_Diagnostic();
                        break;
                case SCSI_CMD_WRITE_10:
-                       SCSI_Command_ReadWrite_10(DATA_WRITE);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(DATA_WRITE);
                        break;
                case SCSI_CMD_READ_10:
-                       SCSI_Command_ReadWrite_10(DATA_READ);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(DATA_READ);
                        break;
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                        /* These commands should just succeed, no handling required */
+                       CommandSuccess = true;
                        CommandBlock.DataTransferLength = 0;
                        break;
                default:
@@ -128,13 +126,25 @@ bool SCSI_DecodeSCSICommand(void)
                        break;
        }
        
-       return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
+       /* Check if command was successfully processed */
+       if (CommandSuccess)
+       {
+               SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+                              SCSI_ASENSEQ_NO_QUALIFIER);
+               
+               return true;
+       }
+
+       return false;
 }
 
 /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
  *  and capabilities to the host.
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Inquiry(void)
+static bool SCSI_Command_Inquiry(void)
 {
        uint16_t AllocationLength  = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[3]);
        uint16_t BytesTransferred  = (AllocationLength < sizeof(InquiryData))? AllocationLength :
@@ -149,7 +159,7 @@ static void SCSI_Command_Inquiry(void)
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
 
        /* Write the INQUIRY data to the endpoint */
@@ -165,12 +175,16 @@ static void SCSI_Command_Inquiry(void)
 
        /* Succeed the command and update the bytes transferred counter */
        CommandBlock.DataTransferLength -= BytesTransferred;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
  *  including the error code and additional error information so that the host can determine why a command failed to complete.
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Request_Sense(void)
+static bool SCSI_Command_Request_Sense(void)
 {
        uint8_t  AllocationLength = CommandBlock.SCSICommandData[4];
        uint8_t  BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
@@ -188,12 +202,16 @@ static void SCSI_Command_Request_Sense(void)
 
        /* Succeed the command and update the bytes transferred counter */
        CommandBlock.DataTransferLength -= BytesTransferred;
+
+       return true;
 }
 
 /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
  *  on the selected Logical Unit (drive), as a number of OS-sized blocks.
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Read_Capacity_10(void)
+static bool SCSI_Command_Read_Capacity_10(void)
 {
        /* Send the total number of logical blocks in the current LUN */
        Endpoint_Write_DWord_BE(LUN_MEDIA_BLOCKS - 1);
@@ -203,20 +221,24 @@ static void SCSI_Command_Read_Capacity_10(void)
 
        /* Check if the current command is being aborted by the host */
        if (IsMassStoreReset)
-         return;
+         return false;
 
        /* Send the endpoint data packet to the host */
        Endpoint_ClearIN();
 
        /* Succeed the command and update the bytes transferred counter */
        CommandBlock.DataTransferLength -= 8;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
  *  board, and indicates if they are present and functioning correctly. Only the Self-Test portion of the diagnostic command is
  *  supported.
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Send_Diagnostic(void)
+static bool SCSI_Command_Send_Diagnostic(void)
 {
        /* Check to see if the SELF TEST bit is not set */
        if (!(CommandBlock.SCSICommandData[1] & (1 << 2)))
@@ -226,7 +248,7 @@ static void SCSI_Command_Send_Diagnostic(void)
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Check to see if all attached Dataflash ICs are functional */
@@ -237,11 +259,13 @@ static void SCSI_Command_Send_Diagnostic(void)
                               SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
                               SCSI_ASENSEQ_NO_QUALIFIER);      
        
-               return;
+               return false;
        }
        
        /* Succeed the command and update the bytes transferred counter */
        CommandBlock.DataTransferLength = 0;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
@@ -249,8 +273,10 @@ static void SCSI_Command_Send_Diagnostic(void)
  *  reading and writing of the data.
  *
  *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_ReadWrite_10(const bool IsDataRead)
+static bool SCSI_Command_ReadWrite_10(const bool IsDataRead)
 {
        uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&CommandBlock.SCSICommandData[2]);
        uint16_t TotalBlocks  = SwapEndian_16(*(uint16_t*)&CommandBlock.SCSICommandData[7]);
@@ -263,7 +289,7 @@ static void SCSI_Command_ReadWrite_10(const bool IsDataRead)
                               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
 
        #if (TOTAL_LUNS > 1)
@@ -279,4 +305,6 @@ static void SCSI_Command_ReadWrite_10(const bool IsDataRead)
 
        /* Update the bytes transferred counter and succeed the command */
        CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+       
+       return true;
 }
index 7bee2ad..7c6d917 100644 (file)
@@ -58,9 +58,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = (key);              \
-                                                                  SenseData.AdditionalSenseCode = (acode); \
-                                                                  SenseData.AdditionalSenseQualifier = (aqual); }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
                bool SCSI_DecodeSCSICommand(void);
                
                #if defined(INCLUDE_FROM_SCSI_C)
-                       static void SCSI_Command_Inquiry(void);
-                       static void SCSI_Command_Request_Sense(void);
-                       static void SCSI_Command_Read_Capacity_10(void);
-                       static void SCSI_Command_Send_Diagnostic(void);
-                       static void SCSI_Command_ReadWrite_10(const bool IsDataRead);
+                       static bool SCSI_Command_Inquiry(void);
+                       static bool SCSI_Command_Request_Sense(void);
+                       static bool SCSI_Command_Read_Capacity_10(void);
+                       static bool SCSI_Command_Send_Diagnostic(void);
+                       static bool SCSI_Command_ReadWrite_10(const bool IsDataRead);
                #endif
                
 #endif
index 0df9ea1..37c8bb0 100644 (file)
@@ -91,7 +91,7 @@
                        /** Determines the currently selected dataflash chip.
                         *
                         *  \return Mask of the currently selected Dataflash chip, either \ref DATAFLASH_NO_CHIP if no chip is selected
-                        *  or a DATAFLASH_CHIPn mask (where n is the chip number).
+                        *          or a DATAFLASH_CHIPn mask (where n is the chip number).
                         */
                        static inline uint8_t Dataflash_GetSelectedChip(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
                        static inline uint8_t Dataflash_GetSelectedChip(void)
index 999959f..45e894d 100644 (file)
   *    depending of if the given bank size is a compile time constant, as the compiler does a better job of optimizing
   *    with basic code
   *  - Changed over all device demos to use a clearer algorithm for the configuring of the application's endpoints
+  *  - Added missing DataflashManager_CheckDataflashOperation() function to the MassStorageKeyboard demo, removed redundant
+  *    SCSI_Codes.h file as these values are part of the MassStorage Class Driver
   *
   *  <b>Fixed:</b>
   *  - Fixed USB_GetHIDReportItemInfo() function modifying the given report item's data when the report item does not exist
   *    within the supplied report of a multiple report HID device
+  *  - Fixed MassStorage based demos and projects resetting the SCSI sense values before the command is executed, leading to
+  *    missed SCSI sense values when the host retrieves the sense key (thanks to Martin Degelsegger)
   *
   *  \section Sec_ChangeLog100807 Version 100807
   *  <b>New:</b>
index 29f9749..1ca22a5 100644 (file)
@@ -86,39 +86,39 @@ SCSI_Request_Sense_Response_t SenseData =
  *  a command failure due to a ILLEGAL REQUEST.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
-       /* Set initial sense data, before the requested command is processed */
-       SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
-                      SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                      SCSI_ASENSEQ_NO_QUALIFIER);
-                                          
+       bool CommandSuccess = false;
+
        /* Run the appropriate SCSI command hander function based on the passed command */
        switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
        {
                case SCSI_CMD_INQUIRY:
-                       SCSI_Command_Inquiry(MSInterfaceInfo);                  
+                       CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);                 
                        break;
                case SCSI_CMD_REQUEST_SENSE:
-                       SCSI_Command_Request_Sense(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
-                       SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                 
+                       CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                        
                        break;
                case SCSI_CMD_SEND_DIAGNOSTIC:
-                       SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
                        break;
                case SCSI_CMD_WRITE_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
                case SCSI_CMD_READ_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
                        break;
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                        /* These commands should just succeed, no handling required */
+                       CommandSuccess = true;
                        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
                        break;
                default:
@@ -129,15 +129,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                        break;
        }
 
-       return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
+       /* Check if command was successfully processed */
+       if (CommandSuccess)
+       {
+               SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+                              SCSI_ASENSEQ_NO_QUALIFIER);
+               
+               return true;
+       }
+
+       return false;
 }
 
 /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
  *  and capabilities to the host.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint16_t AllocationLength  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
        uint16_t BytesTransferred  = (AllocationLength < sizeof(InquiryData))? AllocationLength :
@@ -152,7 +164,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
@@ -167,14 +179,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
  *  including the error code and additional error information so that the host can determine why a command failed to complete.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint8_t  AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
        uint8_t  BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
@@ -187,14 +203,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+       return true;
 }
 
 /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
  *  on the selected Logical Unit (drive), as a number of OS-sized blocks.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
        uint32_t MediaBlockSize        = VIRTUAL_MEMORY_BLOCK_SIZE;
@@ -205,6 +225,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
@@ -212,8 +234,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
  *  supported.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        /* Check to see if the SELF TEST bit is not set */
        if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
@@ -223,7 +247,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Check to see if all attached Dataflash ICs are functional */
@@ -234,11 +258,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
                               SCSI_ASENSEQ_NO_QUALIFIER);      
        
-               return;
+               return false;
        }
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
@@ -247,12 +273,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
-       uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
-       uint16_t TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
+       uint32_t BlockAddress;
+       uint16_t TotalBlocks;
+       
+       /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
+       BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
+
+       /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
+       TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
        
        /* Check if the block address is outside the maximum allowable value for the LUN */
        if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
@@ -262,7 +296,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
                               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
@@ -273,5 +307,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+       
+       return true;
 }
 #endif
index 22c3a1d..6932a81 100644 (file)
@@ -43,6 +43,7 @@
                #include <LUFA/Drivers/USB/USB.h>
                #include <LUFA/Drivers/USB/Class/MassStorage.h>
 
+               #include "StandaloneProgrammer.h"
                #include "Descriptors.h"
                #include "DataflashManager.h"
        
@@ -55,9 +56,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = key;              \
-                                                                  SenseData.AdditionalSenseCode = acode; \
-                                                                  SenseData.AdditionalSenseQualifier = aqual; }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
                        bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
                        
                        #if defined(INCLUDE_FROM_SCSI_C)
-                               static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                               static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                               static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                               static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                               static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
-                                                                     const bool IsDataRead);
+                               static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                               static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                               static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                               static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                               static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+                                                                                                         const bool IsDataRead);
                        #endif
                #endif
                
index 6923f78..a987319 100644 (file)
@@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData =
  *  a command failure due to a ILLEGAL REQUEST.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
-       /* Set initial sense data, before the requested command is processed */
-       SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
-                      SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                      SCSI_ASENSEQ_NO_QUALIFIER);
-                                          
+       bool CommandSuccess = false;
+
        /* Run the appropriate SCSI command hander function based on the passed command */
        switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
        {
                case SCSI_CMD_INQUIRY:
-                       SCSI_Command_Inquiry(MSInterfaceInfo);                  
+                       CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);                 
                        break;
                case SCSI_CMD_REQUEST_SENSE:
-                       SCSI_Command_Request_Sense(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
-                       SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                 
+                       CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                        
                        break;
                case SCSI_CMD_SEND_DIAGNOSTIC:
-                       SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
                        break;
                case SCSI_CMD_WRITE_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
                case SCSI_CMD_READ_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
                        break;
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                        /* These commands should just succeed, no handling required */
+                       CommandSuccess = true;
                        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
                        break;
                default:
@@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                        break;
        }
 
-       return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
+       /* Check if command was successfully processed */
+       if (CommandSuccess)
+       {
+               SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+                              SCSI_ASENSEQ_NO_QUALIFIER);
+               
+               return true;
+       }
+
+       return false;
 }
 
 /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
  *  and capabilities to the host.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint16_t AllocationLength  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
        uint16_t BytesTransferred  = (AllocationLength < sizeof(InquiryData))? AllocationLength :
@@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
@@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
  *  including the error code and additional error information so that the host can determine why a command failed to complete.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint8_t  AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
        uint8_t  BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
@@ -186,14 +202,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+       return true;
 }
 
 /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
  *  on the selected Logical Unit (drive), as a number of OS-sized blocks.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
        uint32_t MediaBlockSize        = VIRTUAL_MEMORY_BLOCK_SIZE;
@@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
@@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
  *  supported.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        /* Check to see if the SELF TEST bit is not set */
        if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
@@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Check to see if all attached Dataflash ICs are functional */
@@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
                               SCSI_ASENSEQ_NO_QUALIFIER);      
        
-               return;
+               return false;
        }
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
@@ -246,13 +272,21 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
-       uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
-       uint16_t TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
-               
+       uint32_t BlockAddress;
+       uint16_t TotalBlocks;
+       
+       /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
+       BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
+
+       /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
+       TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
+       
        /* Check if the block address is outside the maximum allowable value for the LUN */
        if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
        {
@@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
                               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
@@ -272,4 +306,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+       
+       return true;
 }
index c5504b7..5c2112b 100644 (file)
@@ -56,9 +56,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = (key);                   \
-                                                                  SenseData.AdditionalSenseCode = (acode);      \
-                                                                  SenseData.AdditionalSenseQualifier = (aqual); }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
                bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
                
                #if defined(INCLUDE_FROM_SCSI_C)
-                       static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+                       static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                                              const bool IsDataRead);
                #endif
                
index 8999fab..a987319 100644 (file)
@@ -85,39 +85,39 @@ SCSI_Request_Sense_Response_t SenseData =
  *  a command failure due to a ILLEGAL REQUEST.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise
  */
 bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
-       /* Set initial sense data, before the requested command is processed */
-       SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
-                      SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
-                      SCSI_ASENSEQ_NO_QUALIFIER);
-                                          
+       bool CommandSuccess = false;
+
        /* Run the appropriate SCSI command hander function based on the passed command */
        switch (MSInterfaceInfo->State.CommandBlock.SCSICommandData[0])
        {
                case SCSI_CMD_INQUIRY:
-                       SCSI_Command_Inquiry(MSInterfaceInfo);                  
+                       CommandSuccess = SCSI_Command_Inquiry(MSInterfaceInfo);                 
                        break;
                case SCSI_CMD_REQUEST_SENSE:
-                       SCSI_Command_Request_Sense(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Request_Sense(MSInterfaceInfo);
                        break;
                case SCSI_CMD_READ_CAPACITY_10:
-                       SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                 
+                       CommandSuccess = SCSI_Command_Read_Capacity_10(MSInterfaceInfo);                        
                        break;
                case SCSI_CMD_SEND_DIAGNOSTIC:
-                       SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
+                       CommandSuccess = SCSI_Command_Send_Diagnostic(MSInterfaceInfo);
                        break;
                case SCSI_CMD_WRITE_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_WRITE);
                        break;
                case SCSI_CMD_READ_10:
-                       SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
+                       CommandSuccess = SCSI_Command_ReadWrite_10(MSInterfaceInfo, DATA_READ);
                        break;
                case SCSI_CMD_TEST_UNIT_READY:
                case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
                case SCSI_CMD_VERIFY_10:
                        /* These commands should just succeed, no handling required */
+                       CommandSuccess = true;
                        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
                        break;
                default:
@@ -128,15 +128,27 @@ bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
                        break;
        }
 
-       return (SenseData.SenseKey == SCSI_SENSE_KEY_GOOD);
+       /* Check if command was successfully processed */
+       if (CommandSuccess)
+       {
+               SCSI_SET_SENSE(SCSI_SENSE_KEY_GOOD,
+                              SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
+                              SCSI_ASENSEQ_NO_QUALIFIER);
+               
+               return true;
+       }
+
+       return false;
 }
 
 /** Command processing for an issued SCSI INQUIRY command. This command returns information about the device's features
  *  and capabilities to the host.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint16_t AllocationLength  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[3]);
        uint16_t BytesTransferred  = (AllocationLength < sizeof(InquiryData))? AllocationLength :
@@ -151,7 +163,7 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        Endpoint_Write_Stream_LE(&InquiryData, BytesTransferred, NO_STREAM_CALLBACK);
@@ -166,14 +178,18 @@ static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI REQUEST SENSE command. This command returns information about the last issued command,
  *  including the error code and additional error information so that the host can determine why a command failed to complete.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint8_t  AllocationLength = MSInterfaceInfo->State.CommandBlock.SCSICommandData[4];
        uint8_t  BytesTransferred = (AllocationLength < sizeof(SenseData))? AllocationLength : sizeof(SenseData);
@@ -186,14 +202,18 @@ static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterf
 
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= BytesTransferred;
+
+       return true;
 }
 
 /** Command processing for an issued SCSI READ CAPACITY (10) command. This command returns information about the device's capacity
  *  on the selected Logical Unit (drive), as a number of OS-sized blocks.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        uint32_t LastBlockAddressInLUN = (VIRTUAL_MEMORY_BLOCKS - 1);
        uint32_t MediaBlockSize        = VIRTUAL_MEMORY_BLOCK_SIZE;
@@ -204,6 +224,8 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= 8;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI SEND DIAGNOSTIC command. This command performs a quick check of the Dataflash ICs on the
@@ -211,8 +233,10 @@ static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInt
  *  supported.
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
+static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo)
 {
        /* Check to see if the SELF TEST bit is not set */
        if (!(MSInterfaceInfo->State.CommandBlock.SCSICommandData[1] & (1 << 2)))
@@ -222,7 +246,7 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_INVALID_FIELD_IN_CDB,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Check to see if all attached Dataflash ICs are functional */
@@ -233,11 +257,13 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
                               SCSI_ASENSE_NO_ADDITIONAL_INFORMATION,
                               SCSI_ASENSEQ_NO_QUALIFIER);      
        
-               return;
+               return false;
        }
        
        /* Succeed the command and update the bytes transferred counter */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength = 0;
+       
+       return true;
 }
 
 /** Command processing for an issued SCSI READ (10) or WRITE (10) command. This command reads in the block start address
@@ -246,12 +272,20 @@ static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInte
  *
  *  \param[in] MSInterfaceInfo  Pointer to the Mass Storage class interface structure that the command is associated with
  *  \param[in] IsDataRead  Indicates if the command is a READ (10) command or WRITE (10) command (DATA_READ or DATA_WRITE)
+ *
+ *  \return Boolean true if the command completed successfully, false otherwise.
  */
-static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                       const bool IsDataRead)
 {
-       uint32_t BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
-       uint16_t TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
+       uint32_t BlockAddress;
+       uint16_t TotalBlocks;
+       
+       /* Load in the 32-bit block address (SCSI uses big-endian, so have to reverse the byte order) */
+       BlockAddress = SwapEndian_32(*(uint32_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[2]);
+
+       /* Load in the 16-bit total blocks (SCSI uses big-endian, so have to reverse the byte order) */
+       TotalBlocks  = SwapEndian_16(*(uint16_t*)&MSInterfaceInfo->State.CommandBlock.SCSICommandData[7]);
        
        /* Check if the block address is outside the maximum allowable value for the LUN */
        if (BlockAddress >= VIRTUAL_MEMORY_BLOCKS)
@@ -261,7 +295,7 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
                               SCSI_ASENSE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE,
                               SCSI_ASENSEQ_NO_QUALIFIER);
 
-               return;
+               return false;
        }
        
        /* Determine if the packet is a READ (10) or WRITE (10) command, call appropriate function */
@@ -272,4 +306,6 @@ static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfa
 
        /* Update the bytes transferred counter and succeed the command */
        MSInterfaceInfo->State.CommandBlock.DataTransferLength -= ((uint32_t)TotalBlocks * VIRTUAL_MEMORY_BLOCK_SIZE);
+       
+       return true;
 }
index 3171c48..64836c4 100644 (file)
@@ -55,9 +55,9 @@
                 *  \param[in] acode  New SCSI additional sense key to set the additional sense code to
                 *  \param[in] aqual  New SCSI additional sense key qualifier to set the additional sense qualifier code to
                 */
-               #define SCSI_SET_SENSE(key, acode, aqual)  MACROS{ SenseData.SenseKey = (key);                   \
-                                                                  SenseData.AdditionalSenseCode = (acode);      \
-                                                                  SenseData.AdditionalSenseQualifier = (aqual); }MACROE
+               #define SCSI_SET_SENSE(Key, Acode, Aqual)  MACROS{ SenseData.SenseKey                 = (Key);   \
+                                                                  SenseData.AdditionalSenseCode      = (Acode); \
+                                                                  SenseData.AdditionalSenseQualifier = (Aqual); }MACROE
 
                /** Macro for the \ref SCSI_Command_ReadWrite_10() function, to indicate that data is to be read from the storage medium. */
                #define DATA_READ           true
                bool SCSI_DecodeSCSICommand(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
                
                #if defined(INCLUDE_FROM_SCSI_C)
-                       static void SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
-                       static void SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
+                       static bool SCSI_Command_Inquiry(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Request_Sense(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Read_Capacity_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_Send_Diagnostic(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo);
+                       static bool SCSI_Command_ReadWrite_10(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo,
                                                              const bool IsDataRead);
                #endif