uint8_t Audio_Host_GetSetEndpointProperty(USB_ClassInfo_Audio_Host_t* const AudioInterfaceInfo,
			                              const uint8_t DataPipeIndex,
			                              const uint8_t EndpointProperty,
			                              const uint8_t EndpointControl,
			                              const uint16_t DataLength,
			                              void* const Data)
{
	if (!(AudioInterfaceInfo->State.IsActive))
	  return HOST_SENDCONTROL_DeviceDisconnected;

	uint8_t RequestType;
	uint8_t EndpointAddress;

	if (EndpointProperty & 0x80)
	  RequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT);
	else
	  RequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_ENDPOINT);

	Pipe_SelectPipe(DataPipeIndex);
	EndpointAddress = Pipe_GetBoundEndpointAddress();

	USB_ControlRequest = (USB_Request_Header_t)
		{
			.bmRequestType = RequestType,
			.bRequest      = EndpointProperty,
			.wValue        = ((uint16_t)EndpointControl << 8),
			.wIndex        = EndpointAddress,
			.wLength       = DataLength,
		};

	Pipe_SelectPipe(PIPE_CONTROLPIPE);

	return USB_Host_SendControlRequest(Data);
}
Beispiel #2
0
bool Pipe_IsEndpointBound(const uint8_t EndpointAddress)
{
	uint8_t PrevPipeNumber = Pipe_GetCurrentPipe();

	for (uint8_t PNum = 0; PNum < PIPE_TOTAL_PIPES; PNum++)
	{
		Pipe_SelectPipe(PNum);

		if (!(Pipe_IsConfigured()))
		  continue;

		if (Pipe_GetBoundEndpointAddress() == EndpointAddress)
		  return true;
	}

	Pipe_SelectPipe(PrevPipeNumber);
	return false;
}
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.DataINPipe.Address);
	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.DataOUTPipe.Address);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
			return PIPE_RWSTREAM_PipeStalled;
		}

		Pipe_Freeze();
		Pipe_SelectPipe(SIInterfaceInfo->Config.DataINPipe.Address);
		Pipe_Unfreeze();

		if (Pipe_IsStalled())
		{
			USB_Host_ClearEndpointStall(Pipe_GetBoundEndpointAddress());
			return PIPE_RWSTREAM_PipeStalled;
		}

		if (USB_HostState == HOST_STATE_Unattached)
		  return PIPE_RWSTREAM_DeviceDisconnected;
	}

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

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

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

		Pipe_ClearIN();
	}

	Pipe_Freeze();

	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;
}