diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.c b/LUFA/Drivers/USB/Class/Host/MassStorage.c
index 4c23e81530457c01210a0111b9e6539746cabeaa..6c01ed4d8d708e02582fc5620a530ca7ac12daa4 100644
--- a/LUFA/Drivers/USB/Class/Host/MassStorage.c
+++ b/LUFA/Drivers/USB/Class/Host/MassStorage.c
@@ -34,8 +34,6 @@
 #define INCLUDE_FROM_MS_CLASS_HOST_C
 #include "MassStorage.h"
 
-#warning The Mass Storage Host mode Class driver is currently incomplete and is for preview purposes only.
-
 uint8_t MS_Host_ConfigurePipes(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint16_t ConfigDescriptorLength,
 							   uint8_t* DeviceConfigDescriptor)
 {
@@ -478,14 +476,224 @@ uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uin
 }
 
 uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
-                             SCSI_Request_Sense_Response_t* SenseData);
+                             SCSI_Request_Sense_Response_t* SenseData)
+{
+	if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+	  return HOST_SENDCONTROL_DeviceDisconnect;
 
-uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, bool PreventRemoval);							 
+	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
 
-uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddr,
-                                 uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer);
+	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+		{
+			.Signature          = CBW_SIGNATURE,
+			.Tag                = MSInterfaceInfo->State.TransactionTag,
+			.DataTransferLength = sizeof(SCSI_Request_Sense_Response_t),
+			.Flags              = COMMAND_DIRECTION_DATA_IN,
+			.LUN                = LUNIndex,
+			.SCSICommandLength  = 6,
+			.SCSICommandData    =
+				{
+					SCSI_CMD_REQUEST_SENSE,
+					0x00,                                  // Reserved
+					0x00,                                  // Reserved
+					0x00,                                  // Reserved
+					sizeof(SCSI_Request_Sense_Response_t), // Allocation Length
+					0x00                                   // Unused (control)
+				}
+		};
+	
+	if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+
+	if ((ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, &SCSICommandBlock, SenseData)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	MS_CommandStatusWrapper_t SCSICommandStatus;
+	if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if (SCSICommandStatus.Status != SCSI_Command_Pass)
+	  ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
 
-uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddr,
-                                  uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer);
+	return ErrorCode;
+}
+
+uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, bool PreventRemoval)
+{
+	if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+	  return HOST_SENDCONTROL_DeviceDisconnect;
+
+	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+		{
+			.Signature          = CBW_SIGNATURE,
+			.Tag                = MSInterfaceInfo->State.TransactionTag,
+			.DataTransferLength = 0,
+			.Flags              = COMMAND_DIRECTION_DATA_OUT,
+			.LUN                = LUNIndex,
+			.SCSICommandLength  = 6,
+			.SCSICommandData    =
+				{
+					SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL,
+					0x00,                   // Reserved
+					0x00,                   // Reserved
+					PreventRemoval,         // Prevent flag
+					0x00,                   // Reserved
+					0x00                    // Unused (control)
+				}
+		};
+	
+	if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	MS_CommandStatusWrapper_t SCSICommandStatus;
+	if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if (SCSICommandStatus.Status != SCSI_Command_Pass)
+	  ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
+
+	return ErrorCode;
+}
+
+uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddress,
+                                 uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer)
+{
+	if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+	  return HOST_SENDCONTROL_DeviceDisconnect;
+
+	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+		{
+			.Signature          = CBW_SIGNATURE,
+			.Tag                = MSInterfaceInfo->State.TransactionTag,
+			.DataTransferLength = ((uint32_t)Blocks * BlockSize),
+			.Flags              = COMMAND_DIRECTION_DATA_IN,
+			.LUN                = LUNIndex,
+			.SCSICommandLength  = 10,
+			.SCSICommandData    =
+				{
+					SCSI_CMD_READ_10,
+					0x00,                   // Unused (control bits, all off)
+					(BlockAddress >> 24),   // MSB of Block Address
+					(BlockAddress >> 16),
+					(BlockAddress >> 8),
+					(BlockAddress & 0xFF),  // LSB of Block Address
+					0x00,                   // Unused (reserved)
+					0x00,                   // MSB of Total Blocks to Read
+					Blocks,                 // LSB of Total Blocks to Read
+					0x00                    // Unused (control)
+				}
+		};
+
+	if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if ((ErrorCode = MS_Host_WaitForDataReceived(MSInterfaceInfo)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+
+	if ((ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	MS_CommandStatusWrapper_t SCSICommandStatus;
+	if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if (SCSICommandStatus.Status != SCSI_Command_Pass)
+	  ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
+
+	return ErrorCode;
+}
+
+uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddress,
+                                  uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer)
+{
+	if ((USB_HostState != HOST_STATE_Configured) || !(MSInterfaceInfo->State.Active))
+	  return HOST_SENDCONTROL_DeviceDisconnect;
+
+	uint8_t ErrorCode = PIPE_RWSTREAM_NoError;
+
+	MS_CommandBlockWrapper_t SCSICommandBlock = (MS_CommandBlockWrapper_t)
+		{
+			.Signature          = CBW_SIGNATURE,
+			.Tag                = MSInterfaceInfo->State.TransactionTag,
+			.DataTransferLength = ((uint32_t)Blocks * BlockSize),
+			.Flags              = COMMAND_DIRECTION_DATA_OUT,
+			.LUN                = LUNIndex,
+			.SCSICommandLength  = 10,
+			.SCSICommandData    =
+				{
+					SCSI_CMD_WRITE_10,
+					0x00,                   // Unused (control bits, all off)
+					(BlockAddress >> 24),   // MSB of Block Address
+					(BlockAddress >> 16),
+					(BlockAddress >> 8),
+					(BlockAddress & 0xFF),  // LSB of Block Address
+					0x00,                   // Unused (reserved)
+					0x00,                   // MSB of Total Blocks to Write
+					Blocks,                 // LSB of Total Blocks to Write
+					0x00                    // Unused (control)
+				}
+		};
+
+	if ((ErrorCode = MS_Host_SendCommand(MSInterfaceInfo, &SCSICommandBlock)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+
+	if ((ErrorCode = MS_Host_SendReceiveData(MSInterfaceInfo, &SCSICommandBlock, BlockBuffer)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	MS_CommandStatusWrapper_t SCSICommandStatus;
+	if ((ErrorCode = MS_Host_GetReturnedStatus(MSInterfaceInfo, &SCSICommandStatus)) != PIPE_RWSTREAM_NoError)
+	{
+		Pipe_Freeze();
+		return ErrorCode;
+	}
+	
+	if (SCSICommandStatus.Status != SCSI_Command_Pass)
+	  ErrorCode = MS_ERROR_LOGICAL_CMD_FAILED;
+
+	return ErrorCode;
+}
 
 #endif
diff --git a/LUFA/Drivers/USB/Class/Host/MassStorage.h b/LUFA/Drivers/USB/Class/Host/MassStorage.h
index 1678aefee76aa93886fff0ecd4f94091e37ca04d..e64e143a726ecb3705ef331de459de2cbaa830f4 100644
--- a/LUFA/Drivers/USB/Class/Host/MassStorage.h
+++ b/LUFA/Drivers/USB/Class/Host/MassStorage.h
@@ -226,21 +226,74 @@
 			uint8_t MS_Host_GetInquiryData(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
 			                               SCSI_Inquiry_Response_t* InquiryData) ATTR_NON_NULL_PTR_ARG(1, 3);
 
+			/** Sends a TEST UNIT READY command to the device, to determine if it is ready to accept other SCSI commands.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
 			uint8_t MS_Host_TestUnitReady(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex) ATTR_NON_NULL_PTR_ARG(1);
 
+			/** Retrieves the total capacity of the attached USB Mass Storage device, in blocks, and block size.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *  \param[out] DeviceCapacity  Pointer to the location where the capacity information should be stored
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
 			uint8_t MS_Host_ReadDeviceCapacity(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
 			                                   SCSI_Capacity_t* DeviceCapacity) ATTR_NON_NULL_PTR_ARG(1, 3);
 		
+			/** Retrieves the device sense data, indicating the current device state and error codes for the previously
+			 *  issued command.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *  \param[out] SenseData  Pointer to the location where the sense information should be stored
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
 			uint8_t MS_Host_RequestSense(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
 			                             SCSI_Request_Sense_Response_t* SenseData) ATTR_NON_NULL_PTR_ARG(1, 3);
 		
+			/** Issues a PREVENT MEDIUM REMOVAL command, to logically (or, depending on the type of device, physically) lock
+			 *  the device from removal so that blocks of data on the medium can be read or altered.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *  \param[in] PreventRemoval  Boolean true if the device should be locked from removal, false otherwise
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
 			uint8_t MS_Host_PreventAllowMediumRemoval(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex,
 			                                          bool PreventRemoval) ATTR_NON_NULL_PTR_ARG(1);
 			
-			uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddr,
+			/** Reads blocks of data from the attached Mass Storage device's medium.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *  \param[in] BlockAddress  Starting block address within the device to read from
+			 *  \param[in] Blocks  Total number of blocks to read
+			 *  \param[out] BlockBuffer  Pointer to where the read data from the device should be stored
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
+			uint8_t MS_Host_ReadDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddress,
 			                                 uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1, 6);
 		
-			uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddr,
+			/** Writes blocks of data to the attached Mass Storage device's medium.
+			 *
+			 *  \param[in,out] MSInterfaceInfo  Pointer to a structure containing a MS Class host configuration and state
+			 *  \param[in] LUNIndex  LUN index within the device the command is being issued to
+			 *  \param[in] BlockAddress  Starting block address within the device to write to
+			 *  \param[in] Blocks  Total number of blocks to read
+			 *  \param[in] BlockBuffer  Pointer to where the data to write should be sourced from
+			 *
+			 *  \return A value from the \ref Pipe_Stream_RW_ErrorCodes_t enum or MS_ERROR_LOGICAL_CMD_FAILED if not ready
+			 */
+			uint8_t MS_Host_WriteDeviceBlocks(USB_ClassInfo_MS_Host_t* MSInterfaceInfo, uint8_t LUNIndex, uint32_t BlockAddress,
 			                                  uint8_t Blocks, uint16_t BlockSize, void* BlockBuffer) ATTR_NON_NULL_PTR_ARG(1, 6);
 
 	/* Private Interface - For use in library only: */