@ -50,7 +50,8 @@ int main(void)
for ( ; ; )
{
StillImage_Task ( ) ;
StillImageHost_Task ( ) ;
USB_USBTask ( ) ;
}
}
@ -98,6 +99,35 @@ void EVENT_USB_Host_DeviceUnattached(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 ( " Still Image Device Enumerated. \r \n " ) ) ;
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
}
@ -127,214 +157,166 @@ void EVENT_USB_Host_DeviceEnumerationFailed(const uint8_t ErrorCode,
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
}
/** Task to set the configuration of the attached device after it has been enumerated, and to print device information
* through the serial port .
/** Task to print device information through the serial port, and open/close a test PIMA session with the
* attached Still Image device .
*/
void StillImage _Task( void )
void StillImage Host _Task( void )
{
if ( USB_HostState ! = HOST_STATE_Configured )
return ;
uint8_t ErrorCode ;
switch ( USB_HostState )
/* Indicate device busy via the status LEDs */
LEDs_SetAllLEDs ( LEDMASK_USB_BUSY ) ;
puts_P ( PSTR ( " Retrieving Device Info... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 0 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_GETDEVICEINFO ,
. TransactionID = 0x00000000 ,
. Params = { } ,
} ;
/* Send the GETDEVICEINFO block */
SImage_SendBlockHeader ( ) ;
/* Receive the response data block */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Calculate the size of the returned device info data structure */
uint16_t DeviceInfoSize = ( PIMA_ReceivedBlock . DataLength - PIMA_COMMAND_SIZE ( 0 ) ) ;
/* Create a buffer large enough to hold the entire device info */
uint8_t DeviceInfo [ DeviceInfoSize ] ;
/* Read in the data block data (containing device info) */
SImage_ReadData ( DeviceInfo , DeviceInfoSize ) ;
/* Once all the data has been read, the pipe must be cleared before the response can be sent */
Pipe_ClearIN ( ) ;
/* Create a pointer for walking through the info dataset */
uint8_t * DeviceInfoPos = DeviceInfo ;
/* Skip over the data before the unicode device information strings */
DeviceInfoPos + = 8 ; // Skip to VendorExtensionDesc String
DeviceInfoPos + = ( 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ) ; // Skip over VendorExtensionDesc String
DeviceInfoPos + = 2 ; // Skip over FunctionalMode
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Operations Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Events Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Device Properties Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Capture Formats Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Image Formats Array
/* Extract and convert the Manufacturer Unicode string to ASCII and print it through the USART */
char Manufacturer [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , Manufacturer ) ;
printf_P ( PSTR ( " Manufacturer: %s \r \n " ) , Manufacturer ) ;
DeviceInfoPos + = 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ; // Skip over Manufacturer String
/* Extract and convert the Model Unicode string to ASCII and print it through the USART */
char Model [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , Model ) ;
printf_P ( PSTR ( " Model: %s \r \n " ) , Model ) ;
DeviceInfoPos + = 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ; // Skip over Model String
/* Extract and convert the Device Version Unicode string to ASCII and print it through the USART */
char DeviceVersion [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , DeviceVersion ) ;
printf_P ( PSTR ( " Device Version: %s \r \n " ) , DeviceVersion ) ;
/* Receive the final response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
puts_P ( PSTR ( " Opening Session... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 1 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_OPENSESSION ,
. TransactionID = 0x00000000 ,
. Params = { 0x00000001 } ,
} ;
/* Send the OPENSESSION block, open a session with an ID of 0x0001 */
SImage_SendBlockHeader ( ) ;
/* Receive the response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
puts_P ( PSTR ( " Closing Session... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 1 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_CLOSESESSION ,
. TransactionID = 0x00000001 ,
. Params = { 0x00000001 } ,
} ;
/* Send the CLOSESESSION block, close the session with an ID of 0x0001 */
SImage_SendBlockHeader ( ) ;
/* Receive the response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
case HOST_STATE_Addressed :
puts_P ( PSTR ( " Getting Config Data. \r \n " ) ) ;
/* 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 ) ;
/* Indicate error via status LEDs */
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
/* Wait until USB device disconnected */
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* 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 ) ;
/* Indicate error via status LEDs */
LEDs_SetAllLEDs ( LEDMASK_USB_ERROR ) ;
/* Wait until USB device disconnected */
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
puts_P ( PSTR ( " Still Image Device Enumerated. \r \n " ) ) ;
USB_HostState = HOST_STATE_Configured ;
break ;
case HOST_STATE_Configured :
/* Indicate device busy via the status LEDs */
LEDs_SetAllLEDs ( LEDMASK_USB_BUSY ) ;
puts_P ( PSTR ( " Retrieving Device Info... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 0 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_GETDEVICEINFO ,
. TransactionID = 0x00000000 ,
. Params = { } ,
} ;
/* Send the GETDEVICEINFO block */
SImage_SendBlockHeader ( ) ;
/* Receive the response data block */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Calculate the size of the returned device info data structure */
uint16_t DeviceInfoSize = ( PIMA_ReceivedBlock . DataLength - PIMA_COMMAND_SIZE ( 0 ) ) ;
/* Create a buffer large enough to hold the entire device info */
uint8_t DeviceInfo [ DeviceInfoSize ] ;
/* Read in the data block data (containing device info) */
SImage_ReadData ( DeviceInfo , DeviceInfoSize ) ;
/* Once all the data has been read, the pipe must be cleared before the response can be sent */
Pipe_ClearIN ( ) ;
/* Create a pointer for walking through the info dataset */
uint8_t * DeviceInfoPos = DeviceInfo ;
/* Skip over the data before the unicode device information strings */
DeviceInfoPos + = 8 ; // Skip to VendorExtensionDesc String
DeviceInfoPos + = ( 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ) ; // Skip over VendorExtensionDesc String
DeviceInfoPos + = 2 ; // Skip over FunctionalMode
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Operations Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Events Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Supported Device Properties Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Capture Formats Array
DeviceInfoPos + = ( 4 + ( * ( uint32_t * ) DeviceInfoPos < < 1 ) ) ; // Skip over Image Formats Array
/* Extract and convert the Manufacturer Unicode string to ASCII and print it through the USART */
char Manufacturer [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , Manufacturer ) ;
printf_P ( PSTR ( " Manufacturer: %s \r \n " ) , Manufacturer ) ;
DeviceInfoPos + = 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ; // Skip over Manufacturer String
/* Extract and convert the Model Unicode string to ASCII and print it through the USART */
char Model [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , Model ) ;
printf_P ( PSTR ( " Model: %s \r \n " ) , Model ) ;
DeviceInfoPos + = 1 + UNICODE_STRING_LENGTH ( * DeviceInfoPos ) ; // Skip over Model String
/* Extract and convert the Device Version Unicode string to ASCII and print it through the USART */
char DeviceVersion [ * DeviceInfoPos ] ;
UnicodeToASCII ( DeviceInfoPos , DeviceVersion ) ;
printf_P ( PSTR ( " Device Version: %s \r \n " ) , DeviceVersion ) ;
/* Receive the final response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
puts_P ( PSTR ( " Opening Session... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 1 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_OPENSESSION ,
. TransactionID = 0x00000000 ,
. Params = { 0x00000001 } ,
} ;
/* Send the OPENSESSION block, open a session with an ID of 0x0001 */
SImage_SendBlockHeader ( ) ;
/* Receive the response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
puts_P ( PSTR ( " Closing Session... \r \n " ) ) ;
PIMA_SendBlock = ( PIMA_Container_t )
{
. DataLength = PIMA_COMMAND_SIZE ( 1 ) ,
. Type = PIMA_CONTAINER_CommandBlock ,
. Code = PIMA_OPERATION_CLOSESESSION ,
. TransactionID = 0x00000001 ,
. Params = { 0x00000001 } ,
} ;
/* Send the CLOSESESSION block, close the session with an ID of 0x0001 */
SImage_SendBlockHeader ( ) ;
/* Receive the response block from the device */
if ( ( ErrorCode = SImage_ReceiveBlockHeader ( ) ) ! = PIPE_RWSTREAM_NoError )
{
ShowCommandError ( ErrorCode , false ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
/* Verify that the command completed successfully */
if ( ( PIMA_ReceivedBlock . Type ! = PIMA_CONTAINER_ResponseBlock ) | | ( PIMA_ReceivedBlock . Code ! = PIMA_RESPONSE_OK ) )
{
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
}
puts_P ( PSTR ( " Done. \r \n " ) ) ;
/* Indicate device no longer busy */
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
USB_HostState = HOST_STATE_WaitForDeviceRemoval ;
break ;
ShowCommandError ( PIMA_ReceivedBlock . Code , true ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
return ;
}
puts_P ( PSTR ( " Done. \r \n " ) ) ;
/* Indicate device no longer busy */
LEDs_SetAllLEDs ( LEDMASK_USB_READY ) ;
USB_Host_SetDeviceConfiguration ( 0 ) ;
}
/** Function to convert a given Unicode encoded string to ASCII. This function will only work correctly on Unicode