Exemplo n.º 1
0
static uint8_t SImage_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
{
	uint8_t ErrorCode;
	
	PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;

	Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
	Pipe_Unfreeze();

	if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;
	
	uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));

	if (ParamBytes)
	{
		if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
		  return ErrorCode;
	}
	
	Pipe_ClearOUT();	
	Pipe_Freeze();
	
	return PIPE_RWSTREAM_NoError;
}
Exemplo n.º 2
0
uint8_t SI_Host_SendBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
                                PIMA_Container_t* const PIMAHeader)
{
	uint8_t ErrorCode;

	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	if (SIInterfaceInfo->State.IsSessionOpen)
	  PIMAHeader->TransactionID = SIInterfaceInfo->State.TransactionID++;

	Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
	Pipe_Unfreeze();

	if ((ErrorCode = Pipe_Write_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));

	if (ParamBytes)
	{
		if ((ErrorCode = Pipe_Write_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
		  return ErrorCode;
	}

	Pipe_ClearOUT();
	Pipe_Freeze();

	return PIPE_RWSTREAM_NoError;
}
/** Function to send the PIMA command container to the attached still image device. */
void SImage_SendBlockHeader(void)
{
	/* Unfreeze the data OUT pipe ready for data transmission */
	Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);
	Pipe_Unfreeze();

	/* Write the PIMA block to the data OUT pipe */
	Pipe_Write_Stream_LE(&PIMA_SendBlock, PIMA_COMMAND_SIZE(0), NULL);

	/* If the block type is a command, send its parameters (if any) */
	if (PIMA_SendBlock.Type == PIMA_CONTAINER_CommandBlock)
	{
		/* Determine the size of the parameters in the block via the data length attribute */
		uint8_t ParamBytes = (PIMA_SendBlock.DataLength - PIMA_COMMAND_SIZE(0));

		/* Check if any parameters in the command block */
		if (ParamBytes)
		{
			/* Write the PIMA parameters to the data OUT pipe */
			Pipe_Write_Stream_LE(&PIMA_SendBlock.Params, ParamBytes, NULL);
		}

		/* Send the PIMA command block to the attached device */
		Pipe_ClearOUT();
	}

	/* Freeze pipe after use */
	Pipe_Freeze();
}
Exemplo n.º 4
0
uint8_t SI_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
                                   PIMA_Container_t* const PIMAHeader)
{
	uint16_t TimeoutMSRem        = SI_COMMAND_DATA_TIMEOUT_MS;
	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();

	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
	Pipe_Unfreeze();

	while (!(Pipe_IsINReceived()))
	{
		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();

		if (CurrentFrameNumber != PreviousFrameNumber)
		{
			PreviousFrameNumber = CurrentFrameNumber;

			if (!(TimeoutMSRem--))
			  return PIPE_RWSTREAM_Timeout;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
			return PIPE_RWSTREAM_PipeStalled;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
			return PIPE_RWSTREAM_PipeStalled;
		}

		if (USB_HostState == HOST_STATE_Unattached)
		  return PIPE_RWSTREAM_DeviceDisconnected;
	}

	Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);

	if (PIMAHeader->Type == PIMA_CONTAINER_ResponseBlock)
	{
		uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));

		if (ParamBytes)
		  Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);

		Pipe_ClearIN();
	}

	Pipe_Freeze();

	return PIPE_RWSTREAM_NoError;
}
Exemplo n.º 5
0
uint8_t SI_Host_OpenSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	SIInterfaceInfo->State.TransactionID = 0;
	SIInterfaceInfo->State.IsSessionOpen = false;

	PIMA_Container_t PIMABlock = (PIMA_Container_t)
		{
			.DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
			.Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
			.Code          = CPU_TO_LE16(0x1002),
			.Params        = {CPU_TO_LE32(1)},
		};

	if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
	  return SI_ERROR_LOGICAL_CMD_FAILED;

	SIInterfaceInfo->State.IsSessionOpen = true;

	return PIPE_RWSTREAM_NoError;
}

uint8_t SI_Host_CloseSession(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	PIMA_Container_t PIMABlock = (PIMA_Container_t)
		{
			.DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
			.Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
			.Code          = CPU_TO_LE16(0x1003),
			.Params        = {CPU_TO_LE32(1)},
		};

	if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	SIInterfaceInfo->State.IsSessionOpen = false;

	if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
	  return SI_ERROR_LOGICAL_CMD_FAILED;

	return PIPE_RWSTREAM_NoError;
}

uint8_t SI_Host_SendCommand(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo,
                            const uint16_t Operation,
                            const uint8_t TotalParams,
                            uint32_t* const Params)
{
	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	PIMA_Container_t PIMABlock = (PIMA_Container_t)
		{
			.DataLength    = cpu_to_le32(PIMA_COMMAND_SIZE(TotalParams)),
			.Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
			.Code          = cpu_to_le16(Operation),
		};

	memcpy(&PIMABlock.Params, Params, sizeof(uint32_t) * TotalParams);

	if ((ErrorCode = SI_Host_SendBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	return PIPE_RWSTREAM_NoError;
}

uint8_t SI_Host_ReceiveResponse(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo)
{
	uint8_t ErrorCode;
	PIMA_Container_t PIMABlock;

	if ((USB_HostState != HOST_STATE_Configured) || !(SIInterfaceInfo->State.IsActive))
	  return PIPE_RWSTREAM_DeviceDisconnected;

	if ((ErrorCode = SI_Host_ReceiveBlockHeader(SIInterfaceInfo, &PIMABlock)) != PIPE_RWSTREAM_NoError)
	  return ErrorCode;

	if ((PIMABlock.Type != CPU_TO_LE16(PIMA_CONTAINER_ResponseBlock)) || (PIMABlock.Code != CPU_TO_LE16(0x2001)))
	  return SI_ERROR_LOGICAL_CMD_FAILED;

	return PIPE_RWSTREAM_NoError;
}
/** Function to receive a PIMA response container from the attached still image device.
 *
 *  \return A value from the Pipe_Stream_RW_ErrorCodes_t enum
 */
uint8_t SImage_ReceiveBlockHeader(void)
{
	uint16_t TimeoutMSRem        = COMMAND_DATA_TIMEOUT_MS;
	uint16_t PreviousFrameNumber = USB_Host_GetFrameNumber();

	/* Unfreeze the data IN pipe */
	Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);
	Pipe_Unfreeze();

	/* Wait until data received on the IN pipe */
	while (!(Pipe_IsINReceived()))
	{
		uint16_t CurrentFrameNumber = USB_Host_GetFrameNumber();

		/* Check to see if a new frame has been issued (1ms elapsed) */
		if (CurrentFrameNumber != PreviousFrameNumber)
		{
			/* Save the new frame number and decrement the timeout period */
			PreviousFrameNumber = CurrentFrameNumber;
			TimeoutMSRem--;

			/* Check to see if the timeout period for the command has elapsed */
			if (!(TimeoutMSRem))
			  return PIPE_RWSTREAM_Timeout;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIMAGE_DATA_OUT_PIPE);
		Pipe_Unfreeze();

		/* Check if pipe stalled (command failed by device) */
		if (Pipe_IsStalled())
		{
			/* Clear the stall condition on the OUT pipe */
			USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());

			/* Return error code and break out of the loop */
			return PIPE_RWSTREAM_PipeStalled;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIMAGE_DATA_IN_PIPE);
		Pipe_Unfreeze();

		/* Check if pipe stalled (command failed by device) */
		if (Pipe_IsStalled())
		{
			/* Clear the stall condition on the IN pipe */
			USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());

			/* Return error code */
			return PIPE_RWSTREAM_PipeStalled;
		}

		/* Check to see if the device was disconnected, if so exit function */
		if (USB_HostState == HOST_STATE_Unattached)
		  return PIPE_RWSTREAM_DeviceDisconnected;
	}

	/* Load in the response from the attached device */
	Pipe_Read_Stream_LE(&PIMA_ReceivedBlock, PIMA_COMMAND_SIZE(0), NULL);

	/* Check if the returned block type is a response block */
	if (PIMA_ReceivedBlock.Type == PIMA_CONTAINER_ResponseBlock)
	{
		/* Determine the size of the parameters in the block via the data length attribute */
		uint8_t ParamBytes = (PIMA_ReceivedBlock.DataLength - PIMA_COMMAND_SIZE(0));

		/* Check if the device has returned any parameters */
		if (ParamBytes)
		{
			/* Read the PIMA parameters from the data IN pipe */
			Pipe_Read_Stream_LE(&PIMA_ReceivedBlock.Params, ParamBytes, NULL);
		}

		/* Clear pipe bank after use */
		Pipe_ClearIN();
	}

	/* Freeze the IN pipe after use */
	Pipe_Freeze();

	return PIPE_RWSTREAM_NoError;
}
/*------------------------------------------------------------------------------
 * CameraControl_DeviceOperation_Capture
 */
uint16_t CameraControl_DeviceOperation_Capture ( USB_ClassInfo_SI_Host_t* SIInterfaceInfo,
        PTP_STORETYPE_EN enStorageType,
        PTP_FMT_EN enFileFormat )
{
    uint8_t iError = 0;
    uint32_t iStorageID = 0;

    CHECK_CAMERA_CONNECTION;

    // Open a new session
    iError = CameraControl_OpenSession(SIInterfaceInfo);
    if ( iError != PIPE_RWSTREAM_NoError )
    {
        iError = -1;
        goto ExitFunction;
    }

    // Search for the appropriate storage ID given the type
    if ( CameraControl_GetStorageID ( enStorageType, &iStorageID )!=0 )
    {
        printf_P(PSTR("\r\nStorage not found. Run get_storage_info..."));
        iError = -2;
        goto ExitFunction;
    }

    // Initiate capture operation
    //  OpCode 0x100E (PTP_OC_InitiateCapture)
    //  Param1 Storage ID
    //  Param2 Object Format
    PIMA_Container_t PIMABlock = (PIMA_Container_t)
    {
        .DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(2)),
         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
          .Code          = CPU_TO_LE16(PTP_OC_InitiateCapture),
           .Params        = {iStorageID, enFileFormat},
    };

    iError = CameraControl_InitiateTransaction ( SIInterfaceInfo, &PIMABlock );
    if ( iError != PIPE_RWSTREAM_NoError )	goto ExitFunction;

ExitFunction:
    // Close the session
    iError = CameraControl_CloseSession(SIInterfaceInfo);
    if ( iError != PIPE_RWSTREAM_NoError )
    {
    }

    return 0;
}

/*------------------------------------------------------------------------------
 * CameraControl_DeviceOperation_GetPropertyDesc
 */
uint16_t CameraControl_DeviceOperation_GetPropertyDesc ( USB_ClassInfo_SI_Host_t* SIInterfaceInfo,
        PTP_DEVPROPERTY_EN enPropertyType )
{
    /*	uint8_t iError = 0;
    	uint8_t iTemp1 = 0;
    	uint8_t iTemp2 = 0;

    	CHECK_CAMERA_CONNECTION;

    	// Open a new session
    	iError = CameraControl_OpenSession(SIInterfaceInfo);
    	if ( iError != PIPE_RWSTREAM_NoError )
    	{
    		iError = -1;
    		return iError;
    	}

    	// Initiate capture operation
    	//  OpCode 0x1014 (PTP_OC_GetDevicePropDesc)
    	PIMA_Container_t PIMABlock = (PIMA_Container_t)
    		{
    			.DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
    			.Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
    			.Code          = CPU_TO_LE16(PTP_OC_GetDevicePropDesc),
    			.Params        = {enPropertyType},
    		};

    	iError = CameraControl_InitiateTransaction ( SIInterfaceInfo, &PIMABlock );
    	if ( iError != PIPE_RWSTREAM_NoError )	return -1;

    	// Get the size (in bytes) of the dataset
    	uint16_t DatasetSize = (PIMABlock.DataLength - PIMA_COMMAND_SIZE(0));

    	if (DatasetSize==0) return -1;

    	printf_P(PSTR(ESC_FG_CYAN "	Got property info of %d bytes.\r\n" ESC_FG_WHITE), DatasetSize);

    	// Create a buffer large enough to hold the entire device info
    	uint8_t Dataset[DatasetSize];

    	// Read in the data block data
    	SI_Host_ReadData(SIInterfaceInfo, Dataset, DatasetSize);

    	// 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* DatasetPos = Dataset;
    	iTemp1 = DatasetSize;

    	// Read out the description
    	while (iTemp1--)
    	{
    		if ( !(iTemp2 % 16) )
    		{
    			putchar('\r'); putchar('\n');
    		}

    		printf_P ( PSTR("%02x "), *DatasetPos );

    		DatasetPos++;
    		iTemp2++;
    	}
    	putchar('\r'); putchar('\n');

    	// Receive the final response block from the device
    	iError = CameraControl_GetResponseAndCheck (SIInterfaceInfo, &PIMABlock);

    	// Close the session
    	iError = CameraControl_CloseSession(SIInterfaceInfo);
    	if ( iError != PIPE_RWSTREAM_NoError )
    	{
    	}

    	return 0;*/
    return 0;
}


/*------------------------------------------------------------------------------
 * CameraControl_DeviceOperation_GetPropertyDesc
 */
uint16_t CameraControl_DeviceOperation_GetPropertyDescBin ( USB_ClassInfo_SI_Host_t* SIInterfaceInfo,
        PTP_DEVPROPERTY_EN enPropertyType, uint16_t transID )
{
    return CameraControl_GeneralStream_Bin (SIInterfaceInfo,
                                            PTP_OC_GetDevicePropDesc,
                                            enPropertyType,
                                            0,
                                            0,
                                            1,
                                            TP_DATA_PROP_DESC,
                                            transID );
}

/*------------------------------------------------------------------------------
 * CameraControl_DeviceOperation_GetPropertyValBin
 */
uint16_t CameraControl_DeviceOperation_GetPropertyValBin ( USB_ClassInfo_SI_Host_t* SIInterfaceInfo,
        PTP_DEVPROPERTY_EN enPropertyType, uint16_t transID )
{
    return CameraControl_GeneralStream_Bin (SIInterfaceInfo,
                                            PTP_OC_GetDevicePropValue,
                                            enPropertyType,
                                            0,
                                            0,
                                            1,
                                            TP_DATA_PROP_VAL,
                                            transID );
}

/*------------------------------------------------------------------------------
 * CameraControl_GetPropertyVal32Bit
 */
uint16_t CameraControl_GetPropertyVal32Bit	( USB_ClassInfo_SI_Host_t* SIInterfaceInfo, PTP_DEVPROPERTY_EN enPropertyType, uint32_t *iVal )
{
    uint16_t 	ReturnedDataSize;
    uint8_t 	ErrorCode = 0;
    uint8_t		RecData[16] = {0};

    CHECK_CAMERA_CONNECTION;

    SIInterfaceInfo->State.TransactionID = 0;

    // Create PIMA message block
    PIMA_Container_t PIMABlock = (PIMA_Container_t)
    {
        .DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)),
         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
          .Code          = CPU_TO_LE16(PTP_OC_GetDevicePropValue),
           .TransactionID = CPU_TO_LE32(0x00000000),
            .Params        = {enPropertyType},
    };

    ErrorCode = CameraControl_InitiateTransaction ( SIInterfaceInfo, &PIMABlock );

    // Get the size (in bytes) of the device info structure
    ReturnedDataSize = (PIMABlock.DataLength - PIMA_COMMAND_SIZE(0));

    ReturnedDataSize = (ReturnedDataSize>16)?16:ReturnedDataSize;
    SI_Host_ReadData(SIInterfaceInfo, RecData, ReturnedDataSize);

    // Once all the data has been read, the pipe must be cleared before the response can be sent
    Pipe_ClearIN();

    uint8_t * temp = (uint8_t*)((void*)(iVal));
    temp[0] = RecData[0];
    temp[1] = RecData[1];
    temp[2] = RecData[2];
    temp[3] = RecData[3];

    // Receive the final response block from the device
    CameraControl_GetResponseAndCheck (SIInterfaceInfo, &PIMABlock);

    return 0;
}

/*------------------------------------------------------------------------------
 * CameraControl_DeviceOperation_SetPropertyValBin
 */
uint16_t CameraControl_DeviceOperation_SetPropertyValBin ( USB_ClassInfo_SI_Host_t* SIInterfaceInfo,
        PTP_DEVPROPERTY_EN enPropertyType, uint32_t val )
{
    uint16_t 	SentDataSize;
    uint8_t 	ErrorCode = 0;
    uint8_t		*SentData = ((uint8_t*)((void*)(&val)));

    CHECK_CAMERA_CONNECTION;

    SIInterfaceInfo->State.TransactionID = 0;

    // Set the size (in bytes) of the device property val
    if (enPropertyType==TP_PROPERTY_EVENT_ExposureTime||enPropertyType==TP_PROPERTY_EVENT_FocalLength)	// 32 bits
        SentDataSize = 4;
    else SentDataSize = 2;		// 16 bits


    // Create PIMA message block
    PIMA_Container_t PIMABlock = (PIMA_Container_t)
    {
        .DataLength    = CPU_TO_LE32(PIMA_COMMAND_SIZE(1)+SentDataSize),
         .Type          = CPU_TO_LE16(PIMA_CONTAINER_CommandBlock),
          .Code          = CPU_TO_LE16(PTP_OC_SetDevicePropValue),
           .TransactionID = CPU_TO_LE32(0x00000000),
            .Params        = {enPropertyType},
    };

    ErrorCode = CameraControl_InitiateTransaction ( SIInterfaceInfo, &PIMABlock );
    SI_Host_ReadData(SIInterfaceInfo, SentData, SentDataSize);

    // Receive the final response block from the device
    CameraControl_GetResponseAndCheck (SIInterfaceInfo, &PIMABlock);

    return 0;
}
/** Task to set the configuration of the attached device after it has been enumerated, and to print device information
 *  through the serial port.
 */
void StillImage_Task(void)
{
	uint8_t ErrorCode;

	switch (USB_HostState)
	{
		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          = CType_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 != CType_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          = CType_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 != CType_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          = CType_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 != CType_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;
	}
}

/** Function to convert a given Unicode encoded string to ASCII. This function will only work correctly on Unicode
 *  strings which contain ASCII printable characters only.
 *
 *  \param[in] UnicodeString  Pointer to a Unicode encoded input string
 *  \param[out] Buffer        Pointer to a buffer where the converted ASCII string should be stored
 */
void UnicodeToASCII(uint8_t* UnicodeString,
                    char* Buffer)
{
	/* Get the number of characters in the string, skip to the start of the string data */
	uint8_t CharactersRemaining = *(UnicodeString++);
	
	/* Loop through the entire unicode string */
	while (CharactersRemaining--)
	{
		/* Load in the next unicode character (only the lower byte, as only Unicode coded ASCII is supported) */
		*(Buffer++) = *UnicodeString;
		
		/* Jump to the next unicode character */
		UnicodeString += 2;
	}
	
	/* Null terminate the string */
	*Buffer = 0;
}

/** Displays a PIMA command error via the device's serial port.
 *
 *  \param[in] ErrorCode          Error code of the function which failed to complete successfully
 *  \param[in] ResponseCodeError  Indicates if the error is due to a command failed indication from the device, or a communication failure
 */
void ShowCommandError(uint8_t ErrorCode,
                      bool ResponseCodeError)
{
	char* FailureType = ((ResponseCodeError) ? PSTR("Response Code != OK") : PSTR("Transaction Fail"));

	printf_P(PSTR(ESC_FG_RED "Command Error (%S).\r\n"
	                         " -- Error Code %d\r\n" ESC_FG_WHITE), FailureType, ErrorCode);
			
	/* Indicate error via status LEDs */
	LEDs_SetAllLEDs(LEDMASK_USB_ERROR);
}
Exemplo n.º 9
0
static uint8_t SImage_Host_ReceiveBlockHeader(USB_ClassInfo_SI_Host_t* const SIInterfaceInfo, SI_PIMA_Container_t* const PIMAHeader)
{
	uint16_t TimeoutMSRem = COMMAND_DATA_TIMEOUT_MS;

	Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
	Pipe_Unfreeze();
	
	while (!(Pipe_IsReadWriteAllowed()))
	{
		if (USB_INT_HasOccurred(USB_INT_HSOFI))
		{
			USB_INT_Clear(USB_INT_HSOFI);
			TimeoutMSRem--;

			if (!(TimeoutMSRem))
			{
				return PIPE_RWSTREAM_Timeout;
			}
		}
		
		Pipe_Freeze();
		Pipe_SelectPipe(SIInterfaceInfo->Config.DataOUTPipeNumber);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataOUTPipeNumber);
			return PIPE_RWSTREAM_PipeStalled;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipeNumber);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearPipeStall(SIInterfaceInfo->Config.DataINPipeNumber);
			return PIPE_RWSTREAM_PipeStalled;
		}
		  
		if (USB_HostState == HOST_STATE_Unattached)
		  return PIPE_RWSTREAM_DeviceDisconnected;
	}
	
	Pipe_Read_Stream_LE(PIMAHeader, PIMA_COMMAND_SIZE(0), NO_STREAM_CALLBACK);
	
	if (PIMAHeader->Type == CType_ResponseBlock)
	{
		uint8_t ParamBytes = (PIMAHeader->DataLength - PIMA_COMMAND_SIZE(0));

		if (ParamBytes)
		  Pipe_Read_Stream_LE(&PIMAHeader->Params, ParamBytes, NO_STREAM_CALLBACK);
		
		Pipe_ClearIN();
		
		PIMAHeader->Code &= 0x0000000F;
	}
	
	Pipe_Freeze();
	
	return PIPE_RWSTREAM_NoError;
}
Exemplo n.º 10
0
void Camera_Capture(void)
{
	if (USB_HostState != HOST_STATE_Configured)
	  return;

	uint8_t ErrorCode;

	puts_P(PSTR("Taking picture...\r\n"));
	_delay_ms(50);

	PIMA_SendBlock = (PIMA_Container_t)
		{
			.DataLength    = PIMA_COMMAND_SIZE(0),
			.Type          = PIMA_CONTAINER_CommandBlock,
			.Code          = EOS_OC_CAPTURE,
			.TransactionID = 0x00000001,
			.Params        = {},
		};

	/* Send the GETDEVICEINFO block */
	SImage_SendBlockHeader();

	/* Receive the response data block */
	if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError)
	{
		puts_P(PSTR("Error 8\r\n"));
		ShowCommandError(ErrorCode, false);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}

	return;
}


void Camera_SetProperty(uint32_t param, uint32_t val)
{
	if (USB_HostState != HOST_STATE_Configured)
	  return;

	uint8_t ErrorCode;

	puts_P(PSTR("Changing Property...\r\n"));
	_delay_ms(50);

	PIMA_SendBlock = (PIMA_Container_t)
		{
			.DataLength    = PIMA_COMMAND_SIZE(1)+2,
			.Type          = PIMA_CONTAINER_CommandBlock,
			.Code          = EOS_OC_PROPERTY_SET,
			.TransactionID = 0x00000001,
			.Params        = {param},
		};

	/* Send the GETDEVICEINFO block */
	SImage_SendBlockHeader();

	uint8_t		*SendData = ((uint8_t*)((void*)(&val)));

	/* Receive the response data block */
	if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError)
	{
		puts_P(PSTR("Error 9\r\n"));
		ShowCommandError(ErrorCode, false);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}

	SImage_SendData(SendData, 2);

	/* Receive the response data block */
	if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError)
	{
		puts_P(PSTR("Error 12\r\n"));
		ShowCommandError(ErrorCode, false);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}

	return;
}

void Camera_GetModel(void)
{
	if (USB_HostState != HOST_STATE_Configured)
	  return;

	uint8_t ErrorCode;

	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)
	{
		puts_P(PSTR("Error 1\r\n"));
		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);
	_delay_ms(50);

	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);
	_delay_ms(50);

	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\r\n"), DeviceVersion);
	_delay_ms(50);

	/* Receive the final response block from the device */
	if ((ErrorCode = SImage_ReceiveBlockHeader()) != PIPE_RWSTREAM_NoError)
	{
		puts_P(PSTR("Error 2\r\n"));
		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))
	{
		puts_P(PSTR("Error 3\r\n"));
		ShowCommandError(PIMA_ReceivedBlock.Code, true);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}
*/
	return;
}


void Camera_Open(void)
{
	if (USB_HostState != HOST_STATE_Configured)
	  return;

	uint8_t ErrorCode;

	puts_P(PSTR("Opening Session...\r\n"));
	_delay_ms(50);

	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)
	{
		puts_P(PSTR("Error 4\r\n"));
		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))
	{
		puts_P(PSTR("Error 5\r\n"));
		ShowCommandError(PIMA_ReceivedBlock.Code, true);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}
*/
	return;	
}

void Camera_Close(void)
{
	if (USB_HostState != HOST_STATE_Configured)
	  return;

	uint8_t ErrorCode;

	puts_P(PSTR("Closing Session...\r\n"));
	_delay_ms(50);

	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)
	{
		puts_P(PSTR("Error 6\r\n"));
		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))
	{
		puts_P(PSTR("Error 7\r\n"));
		ShowCommandError(PIMA_ReceivedBlock.Code, true);
		USB_Host_SetDeviceConfiguration(0);
		return;
	}
*/
	puts_P(PSTR("Done.\r\n"));
	_delay_ms(50);

	USB_Host_SetDeviceConfiguration(0);
	return;	
}

/** Function to convert a given Unicode encoded string to ASCII. This function will only work correctly on Unicode
 *  strings which contain ASCII printable characters only.
 *
 *  \param[in] UnicodeString  Pointer to a Unicode encoded input string
 *  \param[out] Buffer        Pointer to a buffer where the converted ASCII string should be stored
 */
void UnicodeToASCII(uint8_t* UnicodeString,
                    char* Buffer)
{
	/* Get the number of characters in the string, skip to the start of the string data */
	uint8_t CharactersRemaining = *(UnicodeString++);

	/* Loop through the entire unicode string */
	while (CharactersRemaining--)
	{
		/* Load in the next unicode character (only the lower byte, as only Unicode coded ASCII is supported) */
		*(Buffer++) = *UnicodeString;

		/* Jump to the next unicode character */
		UnicodeString += 2;
	}

	/* Null terminate the string */
	*Buffer = 0;
}

/** Displays a PIMA command error via the device's serial port.
 *
 *  \param[in] ErrorCode          Error code of the function which failed to complete successfully
 *  \param[in] ResponseCodeError  Indicates if the error is due to a command failed indication from the device, or a communication failure
 */
void ShowCommandError(uint8_t ErrorCode,
                      bool ResponseCodeError)
{
	const char* FailureType = ((ResponseCodeError) ? PSTR("Response Code != OK") : PSTR("Transaction Fail"));

	printf_P(PSTR( "Command Error (%S).\r\n"
	                         " -- Error Code %d\r\n" ), FailureType, ErrorCode);
	_delay_ms(50);

}