@ -54,7 +54,8 @@ int main(void)
for ( ; ; )
for ( ; ; )
{
{
MassStorage_Task ( ) ;
MassStorageHost_Task ( ) ;
USB_USBTask ( ) ;
USB_USBTask ( ) ;
}
}
}
}
@ -102,6 +103,35 @@ void EVENT_USB_Host_DeviceUnattached(void)
*/
*/
void EVENT_USB_Host_DeviceEnumerationComplete ( void )
void EVENT_USB_Host_DeviceEnumerationComplete ( void )
{
{
puts_P ( PSTR ( " Getting Config Data. \r \n " ) ) ;
uint8_t ErrorCode ;
/* Get and process the configuration descriptor data */
if ( ( ErrorCode = ProcessConfigurationDescriptor ( ) ) ! = SuccessfulConfigRead )
{
if ( ErrorCode = = ControlError )
puts_P ( PSTR ( ESC_FG_RED " Control Error (Get Configuration). \r \n " ) ) ;
else
puts_P ( PSTR ( ESC_FG_RED " Invalid Device. \r \n " ) ) ;
printf_P ( PSTR ( " -- Error Code: %d \r \n " ESC_FG_WHITE ) , ErrorCode ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
return ;
}
/* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */
if ( ( ErrorCode = USB_Host_SetDeviceConfiguration ( 1 ) ) ! = HOST_SENDCONTROL_Successful )
{
printf_P ( PSTR ( ESC_FG_RED " Control Error (Set Configuration). \r \n "
" -- Error Code: %d \r \n " ESC_FG_WHITE ) , ErrorCode ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
return ;
}
puts_P ( PSTR ( " Mass Storage Disk Enumerated. \r \n " ) ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
}
}
@ -134,240 +164,181 @@ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
/** Task to set the configuration of the attached device after it has been enumerated, and to read in blocks from
/** Task to set the configuration of the attached device after it has been enumerated, and to read in blocks from
* the device and print them to the serial port .
* the device and print them to the serial port .
*/
*/
void MassStorage _Task( void )
void MassStorage Host _Task( void )
{
{
if ( USB_HostState ! = HOST_STATE_Configured )
return ;
/* Indicate device busy via the status LEDs */
LEDs_SetAllLEDs ( LEDMASK_USB_BUSY ) ;
uint8_t ErrorCode ;
uint8_t ErrorCode ;
switch ( USB_HostState )
/* Send the request, display error and wait for device detach if request fails */
if ( ( ErrorCode = MassStore_GetMaxLUN ( & MassStore_MaxLUNIndex ) ) ! = HOST_SENDCONTROL_Successful )
{
ShowDiskReadError ( PSTR ( " Get Max LUN " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Print number of LUNs detected in the attached device */
printf_P ( PSTR ( " Total LUNs: %d - Using first LUN in device. \r \n " ) , ( MassStore_MaxLUNIndex + 1 ) ) ;
/* Reset the Mass Storage device interface, ready for use */
if ( ( ErrorCode = MassStore_MassStorageReset ( ) ) ! = HOST_SENDCONTROL_Successful )
{
ShowDiskReadError ( PSTR ( " Mass Storage Reset " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Get sense data from the device - many devices will not accept any other commands until the sense data
* is read - both on start - up and after a failed command */
SCSI_Request_Sense_Response_t SenseData ;
if ( ( ErrorCode = MassStore_RequestSense ( 0 , & SenseData ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Request Sense " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Set the prevent removal flag for the device, allowing it to be accessed */
if ( ( ErrorCode = MassStore_PreventAllowMediumRemoval ( 0 , true ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Prevent/Allow Medium Removal " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Get inquiry data from the device */
SCSI_Inquiry_Response_t InquiryData ;
if ( ( ErrorCode = MassStore_Inquiry ( 0 , & InquiryData ) ) ! = 0 )
{
{
case HOST_STATE_Addressed :
ShowDiskReadError ( PSTR ( " Inquiry " ) , ErrorCode ) ;
puts_P ( PSTR ( " Getting Config Data. \r \n " ) ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
/* Get and process the configuration descriptor data */
}
if ( ( ErrorCode = ProcessConfigurationDescriptor ( ) ) ! = SuccessfulConfigRead )
{
/* Print vendor and product names of attached device */
if ( ErrorCode = = ControlError )
printf_P ( PSTR ( " Vendor \" %.8s \" , Product \" %.16s \" \r \n " ) , InquiryData . VendorID , InquiryData . ProductID ) ;
puts_P ( PSTR ( ESC_FG_RED " Control Error (Get Configuration). \r \n " ) ) ;
else
/* Wait until disk ready */
puts_P ( PSTR ( ESC_FG_RED " Invalid Device. \r \n " ) ) ;
puts_P ( PSTR ( " Waiting until ready.. " ) ) ;
printf_P ( PSTR ( " -- Error Code: %d \r \n " ESC_FG_WHITE ) , ErrorCode ) ;
for ( ; ; )
{
/* Indicate error via status LEDs */
Serial_SendByte ( ' . ' ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
/* Abort if device removed */
/* Wait until USB device disconnected */
if ( USB_HostState = = HOST_STATE_Unattached )
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
break ;
}
/* Check to see if the attached device is ready for new commands */
ErrorCode = MassStore_TestUnitReady ( 0 ) ;
/* Set the device configuration to the first configuration (rarely do devices use multiple configurations) */
if ( ( ErrorCode = USB_Host_SetDeviceConfiguration ( 1 ) ) ! = HOST_SENDCONTROL_Successful )
/* If attached device is ready, abort the loop */
{
if ( ! ( ErrorCode ) )
printf_P ( PSTR ( ESC_FG_RED " Control Error (Set Configuration). \r \n "
break ;
" -- Error Code: %d \r \n " ESC_FG_WHITE ) , ErrorCode ) ;
/* If an error other than a logical command failure (indicating device busy) returned, abort */
/* Indicate error via status LEDs */
if ( ErrorCode ! = MASS_STORE_SCSI_COMMAND_FAILED )
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
{
ShowDiskReadError ( PSTR ( " Test Unit Ready " ) , ErrorCode ) ;
/* Wait until USB device disconnected */
USB_Host_SetDeviceConfiguration ( 0 ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
return ;
break ;
}
}
}
puts_P ( PSTR ( " Mass Storage Disk Enumerated. \r \n " ) ) ;
puts_P ( PSTR ( " \r \n Retrieving Capacity... " ) ) ;
USB_HostState = HOST_STATE_Configured ;
/* Create new structure for the disk's capacity in blocks and block size */
break ;
SCSI_Capacity_t DiskCapacity ;
case HOST_STATE_Configured :
/* Indicate device busy via the status LEDs */
/* Retrieve disk capacity */
LEDs_SetAllLEDs ( LEDMASK_USB_BUSY ) ;
if ( ( ErrorCode = MassStore_ReadCapacity ( 0 , & DiskCapacity ) ) ! = 0 )
{
/* Send the request, display error and wait for device detach if request fails */
ShowDiskReadError ( PSTR ( " Read Capacity " ) , ErrorCode ) ;
if ( ( ErrorCode = MassStore_GetMaxLUN ( & MassStore_MaxLUNIndex ) ) ! = HOST_SENDCONTROL_Successful )
USB_Host_SetDeviceConfiguration ( 0 ) ;
{
return ;
ShowDiskReadError ( PSTR ( " Get Max LUN " ) , ErrorCode ) ;
}
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
/* Display the disk capacity in blocks * block size bytes */
break ;
printf_P ( PSTR ( " %lu blocks of %lu bytes. \r \n " ) , DiskCapacity . Blocks , DiskCapacity . BlockSize ) ;
}
/* Create a new buffer capable of holding a single block from the device */
/* Print number of LUNs detected in the attached device */
uint8_t BlockBuffer [ DiskCapacity . BlockSize ] ;
printf_P ( PSTR ( " Total LUNs: %d - Using first LUN in device. \r \n " ) , ( MassStore_MaxLUNIndex + 1 ) ) ;
/* Reset the Mass Storage device interface, ready for use */
if ( ( ErrorCode = MassStore_MassStorageReset ( ) ) ! = HOST_SENDCONTROL_Successful )
{
ShowDiskReadError ( PSTR ( " Mass Storage Reset " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Get sense data from the device - many devices will not accept any other commands until the sense data
* is read - both on start - up and after a failed command */
SCSI_Request_Sense_Response_t SenseData ;
if ( ( ErrorCode = MassStore_RequestSense ( 0 , & SenseData ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Request Sense " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Set the prevent removal flag for the device, allowing it to be accessed */
if ( ( ErrorCode = MassStore_PreventAllowMediumRemoval ( 0 , true ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Prevent/Allow Medium Removal " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Get inquiry data from the device */
SCSI_Inquiry_Response_t InquiryData ;
if ( ( ErrorCode = MassStore_Inquiry ( 0 , & InquiryData ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Inquiry " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Print vendor and product names of attached device */
printf_P ( PSTR ( " Vendor \" %.8s \" , Product \" %.16s \" \r \n " ) , InquiryData . VendorID , InquiryData . ProductID ) ;
/* Wait until disk ready */
puts_P ( PSTR ( " Waiting until ready.. " ) ) ;
for ( ; ; )
{
Serial_SendByte ( ' . ' ) ;
/* Abort if device removed */
if ( USB_HostState = = HOST_STATE_Unattached )
break ;
/* Check to see if the attached device is ready for new commands */
ErrorCode = MassStore_TestUnitReady ( 0 ) ;
/* If attached device is ready, abort the loop */
if ( ! ( ErrorCode ) )
break ;
/* If an error other than a logical command failure (indicating device busy) returned, abort */
if ( ErrorCode ! = MASS_STORE_SCSI_COMMAND_FAILED )
{
ShowDiskReadError ( PSTR ( " Test Unit Ready " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
}
puts_P ( PSTR ( " \r \n Retrieving Capacity... " ) ) ;
/* Create new structure for the disk's capacity in blocks and block size */
SCSI_Capacity_t DiskCapacity ;
/* Retrieve disk capacity */
if ( ( ErrorCode = MassStore_ReadCapacity ( 0 , & DiskCapacity ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Read Capacity " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Display the disk capacity in blocks * block size bytes */
printf_P ( PSTR ( " %lu blocks of %lu bytes. \r \n " ) , DiskCapacity . Blocks , DiskCapacity . BlockSize ) ;
/* Create a new buffer capable of holding a single block from the device */
uint8_t BlockBuffer [ DiskCapacity . BlockSize ] ;
/* Read in the first 512 byte block from the device */
if ( ( ErrorCode = MassStore_ReadDeviceBlock ( 0 , 0x00000000 , 1 , DiskCapacity . BlockSize , BlockBuffer ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Read Device Block " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
puts_P ( PSTR ( " \r \n Contents of first block: \r \n " ) ) ;
/* Print out the first block in both HEX and ASCII, 16 bytes per line */
for ( uint16_t Chunk = 0 ; Chunk < ( DiskCapacity . BlockSize > > 4 ) ; Chunk + + )
{
/* Pointer to the start of the current 16-byte chunk in the read block of data */
uint8_t * ChunkPtr = & BlockBuffer [ Chunk < < 4 ] ;
/* Print out the 16 bytes of the chunk in HEX format */
for ( uint8_t ByteOffset = 0 ; ByteOffset < ( 1 < < 4 ) ; ByteOffset + + )
{
char CurrByte = * ( ChunkPtr + ByteOffset ) ;
printf_P ( PSTR ( " %.2X " ) , CurrByte ) ;
}
puts_P ( PSTR ( " " ) ) ;
/* Print out the 16 bytes of the chunk in ASCII format */
for ( uint8_t ByteOffset = 0 ; ByteOffset < ( 1 < < 4 ) ; ByteOffset + + )
{
char CurrByte = * ( ChunkPtr + ByteOffset ) ;
putchar ( isprint ( CurrByte ) ? CurrByte : ' . ' ) ;
}
puts_P ( PSTR ( " \r \n " ) ) ;
/* Read in the first 512 byte block from the device */
}
if ( ( ErrorCode = MassStore_ReadDeviceBlock ( 0 , 0x00000000 , 1 , DiskCapacity . BlockSize , BlockBuffer ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Read Device Block " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
puts_P ( PSTR ( " \r \n Contents of first block: \r \n " ) ) ;
/* Print out the first block in both HEX and ASCII, 16 bytes per line */
for ( uint16_t Chunk = 0 ; Chunk < ( DiskCapacity . BlockSize > > 4 ) ; Chunk + + )
{
/* Pointer to the start of the current 16-byte chunk in the read block of data */
uint8_t * ChunkPtr = & BlockBuffer [ Chunk < < 4 ] ;
/* Print out the 16 bytes of the chunk in HEX format */
for ( uint8_t ByteOffset = 0 ; ByteOffset < ( 1 < < 4 ) ; ByteOffset + + )
{
char CurrByte = * ( ChunkPtr + ByteOffset ) ;
printf_P ( PSTR ( " %.2X " ) , CurrByte ) ;
}
puts_P ( PSTR ( " \r \n \r \n Press board button to read entire ASCII contents of disk... \r \n \r \n " ) ) ;
puts_P ( PSTR ( " " ) ) ;
/* Wait for the board button to be pressed */
while ( ! ( Buttons_GetStatus ( ) & BUTTONS_BUTTON1 ) )
{
/* Abort if device removed */
if ( USB_HostState = = HOST_STATE_Unattached )
break ;
}
/* Abort if device removed */
/* Print out the 16 bytes of the chunk in ASCII format */
if ( USB_HostState = = HOST_STATE_Unattached )
for ( uint8_t ByteOffset = 0 ; ByteOffset < ( 1 < < 4 ) ; ByteOffset + + )
break ;
{
char CurrByte = * ( ChunkPtr + ByteOffset ) ;
/* Print out the entire disk contents in ASCII format */
putchar ( isprint ( CurrByte ) ? CurrByte : ' . ' ) ;
for ( uint32_t CurrBlockAddress = 0 ; CurrBlockAddress < DiskCapacity . Blocks ; CurrBlockAddress + + )
}
{
/* Read in the next block of data from the device */
if ( ( ErrorCode = MassStore_ReadDeviceBlock ( 0 , CurrBlockAddress , 1 , DiskCapacity . BlockSize , BlockBuffer ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Read Device Block " ) , ErrorCode ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Send the ASCII data in the read in block to the serial port */
for ( uint16_t Byte = 0 ; Byte < DiskCapacity . BlockSize ; Byte + + )
{
char CurrByte = BlockBuffer [ Byte ] ;
putchar ( isprint ( CurrByte ) ? CurrByte : ' . ' ) ;
puts_P ( PSTR ( " \r \n " ) ) ;
}
}
/* Abort if device removed */
if ( USB_HostState = = HOST_STATE_Unattached )
break ;
}
/* Indicate device no longer busy */
puts_P ( PSTR ( " \r \n \r \n Press board button to read entire ASCII contents of disk... \r \n \r \n " ) ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
/* Wait until USB device disconnected */
/* Wait for the board button to be pressed */
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
while ( ! ( Buttons_GetStatus ( ) & BUTTONS_BUTTON1 ) )
break ;
{
/* Abort if device removed */
if ( USB_HostState = = HOST_STATE_Unattached )
return ;
}
}
/* Print out the entire disk contents in ASCII format */
for ( uint32_t CurrBlockAddress = 0 ; CurrBlockAddress < DiskCapacity . Blocks ; CurrBlockAddress + + )
{
/* Read in the next block of data from the device */
if ( ( ErrorCode = MassStore_ReadDeviceBlock ( 0 , CurrBlockAddress , 1 , DiskCapacity . BlockSize , BlockBuffer ) ) ! = 0 )
{
ShowDiskReadError ( PSTR ( " Read Device Block " ) , ErrorCode ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Send the ASCII data in the read in block to the serial port */
for ( uint16_t Byte = 0 ; Byte < DiskCapacity . BlockSize ; Byte + + )
{
char CurrByte = BlockBuffer [ Byte ] ;
putchar ( isprint ( CurrByte ) ? CurrByte : ' . ' ) ;
}
}
/* Indicate device no longer busy */
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
}
}
/** Indicates that a communication error has occurred with the attached Mass Storage Device,
/** Indicates that a communication error has occurred with the attached Mass Storage Device,