예제 #1
0
uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length
#if !defined(NO_STREAM_CALLBACKS)
                                 , uint8_t (* const Callback)(void)
#endif
								 )
{
	uint8_t* DataStream = (uint8_t*)(Buffer + Length - 1);
	uint8_t  ErrorCode;
	
	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;

	while (Length--)
	{
		if (!(Endpoint_ReadWriteAllowed()))
		{
			Endpoint_ClearCurrentBank();

			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
			  return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		
		*(DataStream--) = Endpoint_Read_Byte();
	}
	
	return ENDPOINT_RWSTREAM_ERROR_NoError;
}
예제 #2
0
파일: ecmd_lufa.c 프로젝트: sankeq/ethersex
void ecmd_lufa_tx(void) {
  
  /* Select the Serial Tx Endpoint */
  Endpoint_SelectEndpoint(CDC_TX_EPNUM);
  
  /* Wait until Serial Tx Endpoint Ready for Read/Write */
  Endpoint_WaitUntilReady();
      
  /* Write the bytes from the buffer to the endpoint while space is available */
  while (write_len && Endpoint_IsReadWriteAllowed()) {
    /* Write each byte retreived from the buffer to the endpoint */
    Endpoint_Write_Byte(write_buffer[0]);
    write_len--;
    memcpy( write_buffer, &write_buffer[1], write_len );
  }
      
  /* Remember if the packet to send completely fills the endpoint */
  bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
  
  /* Send the data */
  Endpoint_ClearIN();
  
  /* If no more data to send and the last packet filled the endpoint, send an empty packet to release
   * the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */
  if (IsFull && !write_len) {
    /* Wait until Serial Tx Endpoint Ready for Read/Write */
    Endpoint_WaitUntilReady();
    
    /* Send an empty packet to terminate the transfer */
    Endpoint_ClearIN();
  }
}
예제 #3
0
uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length
#if !defined(NO_STREAM_CALLBACKS)
                                 , uint8_t (* const Callback)(void)
#endif
								 )
{
	uint8_t* DataStream = (uint8_t*)Buffer;
	uint8_t  ErrorCode;
	
	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;

	while (Length)
	{
		if (!(Endpoint_IsReadWriteAllowed()))
		{
			Endpoint_ClearOUT();

			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
			  return ENDPOINT_RWSTREAM_CallbackAborted;
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		else
		{
			*(DataStream++) = Endpoint_Read_Byte();
			Length--;
		}
	}
	
	return ENDPOINT_RWSTREAM_NoError;
}
예제 #4
0
uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
{
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return ENDPOINT_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);

	if (!(Endpoint_BytesInEndpoint()))
	  return ENDPOINT_READYWAIT_NoError;

	bool BankFull = !(Endpoint_IsReadWriteAllowed());

	Endpoint_ClearIN();

	if (BankFull)
	{
		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		  return ErrorCode;

		Endpoint_ClearIN();
	}

	return ENDPOINT_READYWAIT_NoError;
}
예제 #5
0
파일: CDC.c 프로젝트: cloud-hot/Jennisense
uint8_t CDC_Device_Flush(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo)
{
	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
	  return ENDPOINT_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);

	if (!(Endpoint_BytesInEndpoint()))
	  return ENDPOINT_READYWAIT_NoError;

	bool BankFull = !(Endpoint_IsReadWriteAllowed());

	Endpoint_ClearIN();

	if (BankFull)
	{
		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		  return ErrorCode;

		Endpoint_ClearIN();
	}

	return ENDPOINT_READYWAIT_NoError;
}
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo,
                            const uint8_t Data)
{
	uint8_t status = 0;
	if ((USB_DeviceState == DEVICE_STATE_Configured) &&	(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS != 0))
	{

		Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpoint.Address);

		if (Endpoint_IsReadWriteAllowed())
		{
			Endpoint_Write_8(Data);
			status = ENDPOINT_READYWAIT_NoError;
		}
		else
		{
			Endpoint_ClearIN();
			status = Endpoint_WaitUntilReady();
		}
	}
	else
	{
		status = ENDPOINT_RWSTREAM_DeviceDisconnected;
	}

	return status;

}
예제 #7
0
uint8_t Endpoint_Discard_Stream(uint16_t Length
#if !defined(NO_STREAM_CALLBACKS)
                                , uint8_t (* const Callback)(void)
#endif
								)
{
	uint8_t  ErrorCode;
	
	while (Length)
	{
		if (!(Endpoint_ReadWriteAllowed()))
		{
			Endpoint_ClearCurrentBank();

			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
			  return ENDPOINT_RWSTREAM_ERROR_CallbackAborted;
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		
		Endpoint_Discard_Byte();
		Length--;
		
		if (!(USB_IsConnected))
		  return ENDPOINT_RWSTREAM_ERROR_DeviceDisconnected;
	}
	
	return ENDPOINT_RWSTREAM_ERROR_NoError;
}
예제 #8
0
uint8_t RNDIS_Device_SendPacket(USB_ClassInfo_RNDIS_Device_t* const RNDISInterfaceInfo,
                                void* Buffer,
                                const uint16_t PacketLength)
{
	uint8_t ErrorCode;

	if ((USB_DeviceState != DEVICE_STATE_Configured) ||
	    (RNDISInterfaceInfo->State.CurrRNDISState != RNDIS_Data_Initialized))
	{
		return ENDPOINT_RWSTREAM_DeviceDisconnected;
	}

	Endpoint_SelectEndpoint(RNDISInterfaceInfo->Config.DataINEndpoint.Address);

	if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
	  return ErrorCode;

	RNDIS_Packet_Message_t RNDISPacketHeader;

	memset(&RNDISPacketHeader, 0, sizeof(RNDIS_Packet_Message_t));

	RNDISPacketHeader.MessageType   = CPU_TO_LE32(REMOTE_NDIS_PACKET_MSG);
	RNDISPacketHeader.MessageLength = cpu_to_le32(sizeof(RNDIS_Packet_Message_t) + PacketLength);
	RNDISPacketHeader.DataOffset    = CPU_TO_LE32(sizeof(RNDIS_Packet_Message_t) - sizeof(RNDIS_Message_Header_t));
	RNDISPacketHeader.DataLength    = cpu_to_le32(PacketLength);

	Endpoint_Write_Stream_LE(&RNDISPacketHeader, sizeof(RNDIS_Packet_Message_t), NULL);
	Endpoint_Write_Stream_LE(Buffer, PacketLength, NULL);
	Endpoint_ClearIN();

	return ENDPOINT_RWSTREAM_NoError;
}
예제 #9
0
/** Function to manage CDC data transmission and reception to and from the host. */
void CDC_Task(void)
{
	char*       ReportString    = NULL;
	uint8_t     JoyStatus_LCL   = Joystick_GetStatus();
	static bool ActionSent      = false;

	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	/* Determine if a joystick action has occurred */
	if (JoyStatus_LCL & JOY_UP)
	  ReportString = "Joystick Up\r\n";
	else if (JoyStatus_LCL & JOY_DOWN)
	  ReportString = "Joystick Down\r\n";
	else if (JoyStatus_LCL & JOY_LEFT)
	  ReportString = "Joystick Left\r\n";
	else if (JoyStatus_LCL & JOY_RIGHT)
	  ReportString = "Joystick Right\r\n";
	else if (JoyStatus_LCL & JOY_PRESS)
	  ReportString = "Joystick Pressed\r\n";
	else
	  ActionSent = false;

	/* Flag management - Only allow one string to be sent per action */
	if ((ReportString != NULL) && (ActionSent == false) && LineEncoding.BaudRateBPS)
	{
		ActionSent = true;

		/* Select the Serial Tx Endpoint */
		Endpoint_SelectEndpoint(CDC_TX_EPADDR);

		/* Write the String to the Endpoint */
		Endpoint_Write_Stream_LE(ReportString, strlen(ReportString), NULL);

		/* Remember if the packet to send completely fills the endpoint */
		bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearIN();

		/* If the last packet filled the endpoint, send an empty packet to release the buffer on
		 * the receiver (otherwise all data will be cached until a non-full packet is received) */
		if (IsFull)
		{
			/* Wait until the endpoint is ready for another packet */
			Endpoint_WaitUntilReady();

			/* Send an empty packet to ensure that the host does not buffer data sent to it */
			Endpoint_ClearIN();
		}
	}

	/* Select the Serial Rx Endpoint */
	Endpoint_SelectEndpoint(CDC_RX_EPADDR);

	/* Throw away any received data from the host */
	if (Endpoint_IsOUTReceived())
	  Endpoint_ClearOUT();
}
예제 #10
0
uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer,
                            uint16_t Length,
                            uint16_t* const BytesProcessed)
{
	uint8_t* DataStream      = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
	uint16_t BytesInTransfer = 0;
	uint8_t  ErrorCode;

	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;

	if (BytesProcessed != NULL)
	{
		Length -= *BytesProcessed;
		TEMPLATE_BUFFER_MOVE(DataStream, *BytesProcessed);
	}

	while (Length)
	{
		if (!(Endpoint_IsReadWriteAllowed()))
		{
			TEMPLATE_CLEAR_ENDPOINT();

			if (BytesProcessed != NULL)
			{
				*BytesProcessed += BytesInTransfer;
				return ENDPOINT_RWSTREAM_IncompleteTransfer;
			}

			#if !defined(INTERRUPT_CONTROL_ENDPOINT)
			USB_USBTask();
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		else
		{
			TEMPLATE_TRANSFER_BYTE(DataStream);
			TEMPLATE_BUFFER_MOVE(DataStream, 1);
			Length--;
			BytesInTransfer++;
		}
	}

	return ENDPOINT_RWSTREAM_NoError;
}
예제 #11
0
uint8_t Device_SendByte(USB_EPInfo_Device_t* EPInfo, const uint8_t Data)
{
	if (USB_DeviceState != DEVICE_STATE_Configured) return ENDPOINT_RWSTREAM_DeviceDisconnected;
	// USB_DeviceState 
	// USBTask.h
	// Indicates the current device state machine state. When in device mode, 
	// this indicates the state via one of the values of the 
	// USB_Device_States_t enum values.
	//
	// DEVICE_STATE_Configured(4)
	// Device.h
	// This state indicates that the device has been enumerated by the host 
	// and is ready for USB communications to begin.
	//
	// ENDPOINT_RWSTREAM_DeviceDisconnected(2)
	// EndpointStream.h
	// Device was disconnected from the host during the transfer.
	
	Endpoint_SelectEndpoint(EPInfo->DataINEPAddress);
	// Endpoint_AVR8.h
	// Select the given endpoint address.
	if (!(Endpoint_IsReadWriteAllowed()))
	// Endpoint_AVR8.h
	// Determines if the currently selected endpoint may be read from 
	// (if data is waiting in the endpoint bank and the endpoint is an OUT 
	// direction, or if the bank is not yet full if the endpoint is an IN 
	// direction). This function will return false if an error has occurred in 
	// the endpoint, if the endpoint is an OUT direction and no packet (or an 
	// empty packet) has been received, or if the endpoint is an IN direction 
	// and the endpoint bank is full.
	{
		Endpoint_ClearIN();
		// Endpoint_AVR8.h
		// Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the next packet and switching to the alternative endpoint bank if double banked
		
		uint8_t ErrorCode;

		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		// Endpoint_WaitUntilReady
		// Endpoint_AVR8.h
		// Spin-loops until the currently selected non-control endpoint is 
		// ready for the next packet of data to be read or written to it.
		//
		// ENDPOINT_READYWAIT_NoError(0)
		// Endpoint_AVR8.h
		// Endpoint is ready for next packet, no error.
			return ErrorCode;
	}

	Endpoint_Write_8(Data);
	// Endpoint_AVR8.h
	// Writes one byte to the currently selected endpoint's bank, for IN direction endpoints.
	return ENDPOINT_READYWAIT_NoError;
}
예제 #12
0
uint8_t Endpoint_Null_Stream(uint16_t Length,
                             uint16_t* const BytesProcessed)
{
	uint8_t  ErrorCode;
	uint16_t BytesInTransfer = 0;
	
	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;
	  
	if (BytesProcessed != NULL)
	  Length -= *BytesProcessed;

	while (Length)
	{
		if (!(Endpoint_IsReadWriteAllowed()))
		{
			Endpoint_ClearIN();

			if (BytesProcessed != NULL)
			{
				*BytesProcessed += BytesInTransfer;
				return ENDPOINT_RWSTREAM_IncompleteTransfer;
			}

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		else
		{
			Endpoint_Write_8(0);

			Length--;
			BytesInTransfer++;
		}
	}
	
	return ENDPOINT_RWSTREAM_NoError;
}
예제 #13
0
/** Handler for unknown V2 protocol commands. This discards all sent data and returns a
 *  STATUS_CMD_UNKNOWN status back to the host.
 *
 *  \param[in] V2Command  Issued V2 Protocol command byte from the host
 */
static void V2Protocol_UnknownCommand(const uint8_t V2Command)
{
	/* Discard all incoming data */
	while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
	{
		Endpoint_ClearOUT();
		Endpoint_WaitUntilReady();
	}

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPNUM);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	Endpoint_Write_Byte(V2Command);
	Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
	Endpoint_ClearIN();
}
예제 #14
0
uint8_t MIDI_Device_Flush(USB_ClassInfo_MIDI_Device_t* const MIDIInterfaceInfo)
{
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return ENDPOINT_RWSTREAM_DeviceDisconnected;

	uint8_t ErrorCode;

	Endpoint_SelectEndpoint(MIDIInterfaceInfo->Config.DataINEndpoint.Address);

	if (Endpoint_BytesInEndpoint())
	{
		Endpoint_ClearIN();

		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		  return ErrorCode;
	}

	return ENDPOINT_READYWAIT_NoError;
}
예제 #15
0
파일: CDC.c 프로젝트: emcute0319/ir-usb-kbd
uint8_t CDC_Device_SendByte(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo, const uint8_t Data)
{
	if ((USB_DeviceState != DEVICE_STATE_Configured) || !(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS))
	  return ENDPOINT_RWSTREAM_DeviceDisconnected;

	Endpoint_SelectEndpoint(CDCInterfaceInfo->Config.DataINEndpointNumber);

	if (!(Endpoint_IsReadWriteAllowed()))
	{	
		Endpoint_ClearIN();

		uint8_t ErrorCode;

		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		  return ErrorCode;
	}

	Endpoint_Write_Byte(Data);
	return ENDPOINT_READYWAIT_NoError;
}
예제 #16
0
uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
                             const uint8_t Data)
{
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return ENDPOINT_RWSTREAM_DeviceDisconnected;

	Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);

	if (!(Endpoint_IsReadWriteAllowed()))
	{
		Endpoint_ClearIN();

		uint8_t ErrorCode;

		if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
		  return ErrorCode;
	}

	Endpoint_Write_8(Data);
	return ENDPOINT_READYWAIT_NoError;
}
예제 #17
0
/** Function to manage CDC data transmission and reception to and from the host for the second CDC interface, which echoes back
 *  all data sent to it from the host.
 */
void CDC2_Task(void)
{
	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

	/* Select the Serial Rx Endpoint */
	Endpoint_SelectEndpoint(CDC2_RX_EPNUM);

	/* Check to see if any data has been received */
	if (Endpoint_IsOUTReceived())
	{
		/* Create a temp buffer big enough to hold the incoming endpoint packet */
		uint8_t  Buffer[Endpoint_BytesInEndpoint()];

		/* Remember how large the incoming packet is */
		uint16_t DataLength = Endpoint_BytesInEndpoint();

		/* Read in the incoming packet into the buffer */
		Endpoint_Read_Stream_LE(&Buffer, DataLength);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearOUT();

		/* Select the Serial Tx Endpoint */
		Endpoint_SelectEndpoint(CDC2_TX_EPNUM);

		/* Write the received data to the endpoint */
		Endpoint_Write_Stream_LE(&Buffer, DataLength);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearIN();

		/* Wait until the endpoint is ready for the next packet */
		Endpoint_WaitUntilReady();

		/* Send an empty packet to prevent host buffering */
		Endpoint_ClearIN();
	}
}
uint8_t TEMPLATE_FUNC_NAME (TEMPLATE_BUFFER_TYPE Buffer,
                            uint16_t Length
                            __CALLBACK_PARAM)
{
	uint8_t* DataStream = ((uint8_t*)Buffer + TEMPLATE_BUFFER_OFFSET(Length));
	uint8_t  ErrorCode;
	
	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;

	#if defined(FAST_STREAM_TRANSFERS)
	uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);

	if (Length >= 8)
	{
		Length -= BytesRemToAlignment;

		switch (BytesRemToAlignment)
		{
			default:
				do
				{
					if (!(Endpoint_IsReadWriteAllowed()))
					{
						TEMPLATE_CLEAR_ENDPOINT();

						#if !defined(NO_STREAM_CALLBACKS)
						if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
						  return ENDPOINT_RWSTREAM_CallbackAborted;
						#endif

						if ((ErrorCode = Endpoint_WaitUntilReady()))
						  return ErrorCode;
					}

					Length -= 8;
					
					TEMPLATE_TRANSFER_BYTE(DataStream);
			case 7: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 6: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 5: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 4: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 3: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 2: TEMPLATE_TRANSFER_BYTE(DataStream);
			case 1:	TEMPLATE_TRANSFER_BYTE(DataStream);
				} while (Length >= 8);	
		}
	}
	#endif

	while (Length)
	{
		if (!(Endpoint_IsReadWriteAllowed()))
		{
			TEMPLATE_CLEAR_ENDPOINT();

			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
			  return ENDPOINT_RWSTREAM_CallbackAborted;
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		else
		{
			TEMPLATE_TRANSFER_BYTE(DataStream);
			Length--;
		}
	}

	return ENDPOINT_RWSTREAM_NoError;
}
예제 #19
0
/** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host.
 *  This routine decodes the issued command and passes off the handling of the command to the
 *  appropriate function.
 */
void V2Protocol_ProcessCommand(void)
{
	uint8_t V2Command = Endpoint_Read_8();

	/* Start the watchdog with timeout interrupt enabled to manage the timeout */
	TimeoutExpired = false;
	wdt_enable(WDTO_1S);
	WDTCSR |= (1 << WDIE);

	switch (V2Command)
	{
		case CMD_SIGN_ON:
			V2Protocol_SignOn();
			break;
		case CMD_SET_PARAMETER:
		case CMD_GET_PARAMETER:
			V2Protocol_GetSetParam(V2Command);
			break;
		case CMD_LOAD_ADDRESS:
			V2Protocol_LoadAddress();
			break;
		case CMD_RESET_PROTECTION:
			V2Protocol_ResetProtection();
			break;
#if defined(ENABLE_ISP_PROTOCOL)
		case CMD_ENTER_PROGMODE_ISP:
			ISPProtocol_EnterISPMode();
			break;
		case CMD_LEAVE_PROGMODE_ISP:
			ISPProtocol_LeaveISPMode();
			break;
		case CMD_PROGRAM_FLASH_ISP:
		case CMD_PROGRAM_EEPROM_ISP:
			ISPProtocol_ProgramMemory(V2Command);
			break;
		case CMD_READ_FLASH_ISP:
		case CMD_READ_EEPROM_ISP:
			ISPProtocol_ReadMemory(V2Command);
			break;
		case CMD_CHIP_ERASE_ISP:
			ISPProtocol_ChipErase();
			break;
		case CMD_READ_FUSE_ISP:
		case CMD_READ_LOCK_ISP:
		case CMD_READ_SIGNATURE_ISP:
		case CMD_READ_OSCCAL_ISP:
			ISPProtocol_ReadFuseLockSigOSCCAL(V2Command);
			break;
		case CMD_PROGRAM_FUSE_ISP:
		case CMD_PROGRAM_LOCK_ISP:
			ISPProtocol_WriteFuseLock(V2Command);
			break;
		case CMD_SPI_MULTI:
			ISPProtocol_SPIMulti();
			break;
#endif
#if defined(ENABLE_XPROG_PROTOCOL)
		case CMD_XPROG_SETMODE:
			XPROGProtocol_SetMode();
			break;
		case CMD_XPROG:
			XPROGProtocol_Command();
			break;
#endif
		default:
			V2Protocol_UnknownCommand(V2Command);
			break;
	}

	/* Disable the timeout management watchdog timer */
	wdt_disable();

	Endpoint_WaitUntilReady();
	Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
}
예제 #20
0
/** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host.
 *  This routine decodes the issued command and passes off the handling of the command to the
 *  appropriate function.
 */
void V2Protocol_ProcessCommand(void)
{
	uint8_t V2Command = Endpoint_Read_Byte();

	/* Start the timeout management timer */
	TimeoutTicksRemaining = COMMAND_TIMEOUT_TICKS;
	TCCR0B = ((1 << CS02) | (1 << CS00));

	switch (V2Command)
	{
		case CMD_SIGN_ON:
			V2Protocol_SignOn();
			break;
		case CMD_SET_PARAMETER:
		case CMD_GET_PARAMETER:
			V2Protocol_GetSetParam(V2Command);
			break;
		case CMD_LOAD_ADDRESS:
			V2Protocol_LoadAddress();
			break;
		case CMD_RESET_PROTECTION:
			V2Protocol_ResetProtection();
			break;
#if defined(ENABLE_ISP_PROTOCOL)
		case CMD_ENTER_PROGMODE_ISP:
			ISPProtocol_EnterISPMode();
			break;
		case CMD_LEAVE_PROGMODE_ISP:
			ISPProtocol_LeaveISPMode();
			break;
		case CMD_PROGRAM_FLASH_ISP:
		case CMD_PROGRAM_EEPROM_ISP:
			ISPProtocol_ProgramMemory(V2Command);
			break;
		case CMD_READ_FLASH_ISP:
		case CMD_READ_EEPROM_ISP:
			ISPProtocol_ReadMemory(V2Command);
			break;
		case CMD_CHIP_ERASE_ISP:
			ISPProtocol_ChipErase();
			break;
		case CMD_READ_FUSE_ISP:
		case CMD_READ_LOCK_ISP:
		case CMD_READ_SIGNATURE_ISP:
		case CMD_READ_OSCCAL_ISP:
			ISPProtocol_ReadFuseLockSigOSCCAL(V2Command);
			break;
		case CMD_PROGRAM_FUSE_ISP:
		case CMD_PROGRAM_LOCK_ISP:
			ISPProtocol_WriteFuseLock(V2Command);
			break;
		case CMD_SPI_MULTI:
			ISPProtocol_SPIMulti();
			break;
#endif
#if defined(ENABLE_XPROG_PROTOCOL)
		case CMD_XPROG_SETMODE:
			XPROGProtocol_SetMode();
			break;
		case CMD_XPROG:
			XPROGProtocol_Command();
			break;
#endif
		default:
			V2Protocol_UnknownCommand(V2Command);
			break;
	}

	/* Disable the timeout management timer */
	TCCR0B = 0;

	Endpoint_WaitUntilReady();
	Endpoint_SelectEndpoint(AVRISP_DATA_OUT_EPNUM);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
}
예제 #21
0
/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */
void CDC_Task(void)
{
	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;
	  
#if 0
	/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
			 handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
	*/

	USB_Notification_Header_t Notification = (USB_Notification_Header_t)
		{
			.NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
			.Notification     = NOTIF_SerialState,
			.wValue           = 0,
			.wIndex           = 0,
			.wLength          = sizeof(uint16_t),
		};
		
	uint16_t LineStateMask;
	
	// Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
	
	Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
	Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
	Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
	Endpoint_ClearIN();
#endif

	/* Select the Serial Rx Endpoint */
	Endpoint_SelectEndpoint(CDC_RX_EPNUM);
	
	/* Check to see if a packet has been received from the host */
	if (Endpoint_IsOUTReceived())
	{
		/* Read the bytes in from the endpoint into the buffer while space is available */
		while (Endpoint_BytesInEndpoint() && (Rx_Buffer.Elements != BUFF_STATICSIZE))
		{
			/* Store each character from the endpoint */
			Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
		}
		
		/* Check to see if all bytes in the current packet have been read */
		if (!(Endpoint_BytesInEndpoint()))
		{
			/* Clear the endpoint buffer */
			Endpoint_ClearOUT();
		}
	}
	
	/* Check if Rx buffer contains data - if so, send it */
	if (Rx_Buffer.Elements)
	  Serial_TxByte(Buffer_GetElement(&Rx_Buffer));

	/* Select the Serial Tx Endpoint */
	Endpoint_SelectEndpoint(CDC_TX_EPNUM);

	/* Check if the Tx buffer contains anything to be sent to the host */
	if ((Tx_Buffer.Elements) && LineEncoding.BaudRateBPS)
	{
		/* Wait until Serial Tx Endpoint Ready for Read/Write */
		Endpoint_WaitUntilReady();
		
		/* Write the bytes from the buffer to the endpoint while space is available */
		while (Tx_Buffer.Elements && Endpoint_IsReadWriteAllowed())
		{
			/* Write each byte retreived from the buffer to the endpoint */
			Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
		}
		
		/* Remember if the packet to send completely fills the endpoint */
		bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
		
		/* Send the data */
		Endpoint_ClearIN();

		/* If no more data to send and the last packet filled the endpoint, send an empty packet to release
		 * the buffer on the receiver (otherwise all data will be cached until a non-full packet is received) */
		if (IsFull && !(Tx_Buffer.Elements))
		{
			/* Wait until Serial Tx Endpoint Ready for Read/Write */
			Endpoint_WaitUntilReady();
				
			/* Send an empty packet to terminate the transfer */
			Endpoint_ClearIN();
		}
	}
}

/** ISR to handle the USART receive complete interrupt, fired each time the USART has received a character. This stores the received
 *  character into the Tx_Buffer circular buffer for later transmission to the host.
 */
ISR(USART1_RX_vect, ISR_BLOCK)
{
	uint8_t ReceivedByte = UDR1;
	
	/* Only store received characters if the USB interface is connected */
	if ((USB_DeviceState == DEVICE_STATE_Configured)) {// && LineEncoding.BaudRateBPS
	  Buffer_StoreElement(&Tx_Buffer, ReceivedByte);
	}
}
/** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes,
 *  words or pages of data to the attached device.
 *
 *  \param[in] V2Command  Issued V2 Protocol command byte from the host
 */
void ISPProtocol_ProgramMemory(uint8_t V2Command)
{
	struct
	{
		uint16_t BytesToWrite;
		uint8_t  ProgrammingMode;
		uint8_t  DelayMS;
		uint8_t  ProgrammingCommands[3];
		uint8_t  PollValue1;
		uint8_t  PollValue2;
		uint8_t  ProgData[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
	} Write_Memory_Params;      // whole page and ACK the packet as fast as possible to prevent it from aborting

	Endpoint_Read_Stream_LE(&Write_Memory_Params, (sizeof(Write_Memory_Params) -
	                                               sizeof(Write_Memory_Params.ProgData)), NULL);
	Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);

	if (Write_Memory_Params.BytesToWrite > sizeof(Write_Memory_Params.ProgData))
	{
		Endpoint_ClearOUT();
		Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
		Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

		Endpoint_Write_8(V2Command);
		Endpoint_Write_8(STATUS_CMD_FAILED);
		Endpoint_ClearIN();
		return;
	}

	Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite, NULL);

	// The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need
	// to catch this and discard it before continuing on with packet processing to prevent communication issues
	if (((sizeof(uint8_t) + sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData)) +
	    Write_Memory_Params.BytesToWrite) % AVRISP_DATA_EPSIZE == 0)
	{
		Endpoint_ClearOUT();
		Endpoint_WaitUntilReady();
	}

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	uint8_t  ProgrammingStatus = STATUS_CMD_OK;
	uint8_t  PollValue         = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
	                                                                    Write_Memory_Params.PollValue2;
	uint16_t PollAddress       = 0;
	uint8_t* NextWriteByte     = Write_Memory_Params.ProgData;
	uint16_t PageStartAddress  = (CurrentAddress & 0xFFFF);

	for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
	{
		uint8_t ByteToWrite     = *(NextWriteByte++);
		uint8_t ProgrammingMode = Write_Memory_Params.ProgrammingMode;

		/* Check to see if we need to send a LOAD EXTENDED ADDRESS command to the target */
		if (MustLoadExtendedAddress)
		{
			ISPTarget_LoadExtendedAddress();
			MustLoadExtendedAddress = false;
		}

		ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
		ISPTarget_SendByte(CurrentAddress >> 8);
		ISPTarget_SendByte(CurrentAddress & 0xFF);
		ISPTarget_SendByte(ByteToWrite);

		/* AVR FLASH addressing requires us to modify the write command based on if we are writing a high
		 * or low byte at the current word address */
		if (V2Command == CMD_PROGRAM_FLASH_ISP)
		  Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;

		/* Check to see if we have a valid polling address */
		if (!(PollAddress) && (ByteToWrite != PollValue))
		{
			if ((CurrentByte & 0x01) && (V2Command == CMD_PROGRAM_FLASH_ISP))
			  Write_Memory_Params.ProgrammingCommands[2] |=  READ_WRITE_HIGH_BYTE_MASK;
			else
			  Write_Memory_Params.ProgrammingCommands[2] &= ~READ_WRITE_HIGH_BYTE_MASK;

			PollAddress = (CurrentAddress & 0xFFFF);
		}

		/* If in word programming mode, commit the byte to the target's memory */
		if (!(ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK))
		{
			/* If the current polling address is invalid, switch to timed delay write completion mode */
			if (!(PollAddress) && !(ProgrammingMode & PROG_MODE_WORD_READYBUSY_MASK))
			  ProgrammingMode = (ProgrammingMode & ~PROG_MODE_WORD_VALUE_MASK) | PROG_MODE_WORD_TIMEDELAY_MASK;

			ProgrammingStatus = ISPTarget_WaitForProgComplete(ProgrammingMode, PollAddress, PollValue,
			                                                  Write_Memory_Params.DelayMS,
			                                                  Write_Memory_Params.ProgrammingCommands[2]);

			/* Abort the programming loop early if the byte/word programming failed */
			if (ProgrammingStatus != STATUS_CMD_OK)
			  break;

			/* Must reset the polling address afterwards, so it is not erroneously used for the next byte */
			PollAddress = 0;
		}

		/* EEPROM just increments the address each byte, flash needs to increment on each word and
		 * also check to ensure that a LOAD EXTENDED ADDRESS command is issued each time the extended
		 * address boundary has been crossed during FLASH memory programming */
		if ((CurrentByte & 0x01) || (V2Command == CMD_PROGRAM_EEPROM_ISP))
		{
			CurrentAddress++;

			if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF))
			  MustLoadExtendedAddress = true;
		}
	}

	/* If the current page must be committed, send the PROGRAM PAGE command to the target */
	if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK)
	{
		ISPTarget_SendByte(Write_Memory_Params.ProgrammingCommands[1]);
		ISPTarget_SendByte(PageStartAddress >> 8);
		ISPTarget_SendByte(PageStartAddress & 0xFF);
		ISPTarget_SendByte(0x00);

		/* Check if polling is enabled and possible, if not switch to timed delay mode */
		if ((Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_VALUE_MASK) && !(PollAddress))
		{
			Write_Memory_Params.ProgrammingMode = (Write_Memory_Params.ProgrammingMode & ~PROG_MODE_PAGED_VALUE_MASK) |
												   PROG_MODE_PAGED_TIMEDELAY_MASK;
		}

		ProgrammingStatus = ISPTarget_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
		                                                  Write_Memory_Params.DelayMS,
		                                                  Write_Memory_Params.ProgrammingCommands[2]);

		/* Check to see if the FLASH address has crossed the extended address boundary */
		if ((V2Command == CMD_PROGRAM_FLASH_ISP) && !(CurrentAddress & 0xFFFF))
		  MustLoadExtendedAddress = true;
	}
예제 #23
0
/** Function to manage CDC data transmission and reception to and from the host. */
void CDC_Task(void)
{
	char*       ReportString    = NULL;
	static bool ActionSent      = false;

	/* Device must be connected and configured for the task to run */
	if (USB_DeviceState != DEVICE_STATE_Configured)
	  return;

#if 0
	/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
	 *       handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
	 */
	USB_Notification_Header_t Notification = (USB_Notification_Header_t)
		{
			.NotificationType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
			.Notification     = NOTIF_SerialState,
			.wValue           = 0,
			.wIndex           = 0,
			.wLength          = sizeof(uint16_t),
		};

	uint16_t LineStateMask;

	// Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host

	Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
	Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
	Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
	Endpoint_ClearIN();
#endif

	/* Determine if a joystick action has occurred 
	if (JoyStatus_LCL & JOY_UP)
	  ReportString = "Joystick Up\r\n";
	else if (JoyStatus_LCL & JOY_DOWN)
	  ReportString = "Joystick Down\r\n";
	else if (JoyStatus_LCL & JOY_LEFT)
	  ReportString = "Joystick Left\r\n";
	else if (JoyStatus_LCL & JOY_RIGHT)
	  ReportString = "Joystick Right\r\n";
	else if (JoyStatus_LCL & JOY_PRESS)
	  ReportString = "Joystick Pressed\r\n";
	else */
	  ActionSent = false;

	/* Flag management - Only allow one string to be sent per action */
	if ((ReportString != NULL) && (ActionSent == false) && sport.BaudRateBPS)
	{
		ActionSent = true;

		/* Select the Serial Tx Endpoint */
		Endpoint_SelectEndpoint(CDC_TX_EPNUM);

		/* Write the String to the Endpoint */
		Endpoint_Write_Stream_LE(ReportString, strlen(ReportString), NULL);

		/* Remember if the packet to send completely fills the endpoint */
		bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);

		/* Finalize the stream transfer to send the last packet */
		Endpoint_ClearIN();

		/* If the last packet filled the endpoint, send an empty packet to release the buffer on
		 * the receiver (otherwise all data will be cached until a non-full packet is received) */
		if (IsFull)
		{
			/* Wait until the endpoint is ready for another packet */
			Endpoint_WaitUntilReady();

			/* Send an empty packet to ensure that the host does not buffer data sent to it */
			Endpoint_ClearIN();
		}
	}

	/* Select the Serial Rx Endpoint */
	Endpoint_SelectEndpoint(CDC_RX_EPNUM);

	/* Throw away any received data from the host */
	if (Endpoint_IsOUTReceived())
	  Endpoint_ClearOUT();
}
예제 #24
0
uint8_t Endpoint_Discard_Stream(uint16_t Length
#if !defined(NO_STREAM_CALLBACKS)
                                , StreamCallbackPtr_t Callback
#endif
								)
{
	uint8_t  ErrorCode;
	
	if ((ErrorCode = Endpoint_WaitUntilReady()))
	  return ErrorCode;

	#if defined(FAST_STREAM_TRANSFERS)
	uint8_t BytesRemToAlignment = (Endpoint_BytesInEndpoint() & 0x07);

	if (Length >= 8)
	{
		Length -= BytesRemToAlignment;

		switch (BytesRemToAlignment)
		{
			default:
				do
				{
					if (!(Endpoint_IsReadWriteAllowed()))
					{
						Endpoint_ClearOUT();

						#if !defined(NO_STREAM_CALLBACKS)
						if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
						  return ENDPOINT_RWSTREAM_CallbackAborted;
						#endif

						if ((ErrorCode = Endpoint_WaitUntilReady()))
						  return ErrorCode;
					}

					Length -= 8;
					
					Endpoint_Discard_Byte();
			case 7: Endpoint_Discard_Byte();
			case 6: Endpoint_Discard_Byte();
			case 5: Endpoint_Discard_Byte();
			case 4: Endpoint_Discard_Byte();
			case 3: Endpoint_Discard_Byte();
			case 2: Endpoint_Discard_Byte();
			case 1:	Endpoint_Discard_Byte();
				} while (Length >= 8);	
		}
	}
	#endif

	while (Length)
	{
		if (!(Endpoint_IsReadWriteAllowed()))
		{
			Endpoint_ClearOUT();

			#if !defined(NO_STREAM_CALLBACKS)
			if ((Callback != NULL) && (Callback() == STREAMCALLBACK_Abort))
			  return ENDPOINT_RWSTREAM_CallbackAborted;
			#endif

			if ((ErrorCode = Endpoint_WaitUntilReady()))
			  return ErrorCode;
		}
		else
		{
			Endpoint_Discard_Byte();
			Length--;
		}
	}
	
	return ENDPOINT_RWSTREAM_NoError;
}
예제 #25
0
/** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */
static void XPROGProtocol_WriteMemory(void)
{
	uint8_t ReturnStatus = XPROG_ERR_OK;

	struct
	{
		uint8_t  MemoryType;
		uint8_t  PageMode;
		uint32_t Address;
		uint16_t Length;
		uint8_t  ProgData[256];
	} WriteMemory_XPROG_Params;

	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
	                                                    sizeof(WriteMemory_XPROG_Params).ProgData), NULL);
	WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
	WriteMemory_XPROG_Params.Length  = SwapEndian_16(WriteMemory_XPROG_Params.Length);
	Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length, NULL);

	// The driver will terminate transfers that are a round multiple of the endpoint bank in size with a ZLP, need
	// to catch this and discard it before continuing on with packet processing to prevent communication issues
	if (((sizeof(uint8_t) + sizeof(WriteMemory_XPROG_Params) - sizeof(WriteMemory_XPROG_Params.ProgData)) +
	    WriteMemory_XPROG_Params.Length) % AVRISP_DATA_EPSIZE == 0)
	{
		Endpoint_ClearOUT();
		Endpoint_WaitUntilReady();
	}

	Endpoint_ClearOUT();
	Endpoint_SelectEndpoint(AVRISP_DATA_IN_EPADDR);
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);

	if (XPROG_SelectedProtocol == XPROG_PROTOCOL_PDI)
	{
		/* Assume FLASH page programming by default, as it is the common case */
		uint8_t WriteCommand     = XMEGA_NVM_CMD_WRITEFLASHPAGE;
		uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
		uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
		bool    PagedMemory      = true;

		switch (WriteMemory_XPROG_Params.MemoryType)
		{
			case XPROG_MEM_TYPE_APPL:
				WriteCommand     = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
				break;
			case XPROG_MEM_TYPE_BOOT:
				WriteCommand     = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
				break;
			case XPROG_MEM_TYPE_EEPROM:
				WriteCommand     = XMEGA_NVM_CMD_ERASEWRITEEEPROMPAGE;
				WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
				EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
				break;
			case XPROG_MEM_TYPE_USERSIG:
				WriteCommand     = XMEGA_NVM_CMD_WRITEUSERSIG;
				break;
			case XPROG_MEM_TYPE_FUSE:
				WriteCommand     = XMEGA_NVM_CMD_WRITEFUSE;
				PagedMemory      = false;
				break;
			case XPROG_MEM_TYPE_LOCKBITS:
				WriteCommand     = XMEGA_NVM_CMD_WRITELOCK;
				PagedMemory      = false;
				break;
		}

		/* Send the appropriate memory write commands to the device, indicate timeout if occurred */
		if ((PagedMemory && !(XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
													   WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
													   WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length))) ||
		   (!PagedMemory && !(XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
													   WriteMemory_XPROG_Params.ProgData[0]))))
		{
			ReturnStatus = XPROG_ERR_TIMEOUT;
		}
	}
	else
	{
		/* Send write command to the TPI device, indicate timeout if occurred */
		if (!(TINYNVM_WriteMemory(WriteMemory_XPROG_Params.Address, WriteMemory_XPROG_Params.ProgData,
		      WriteMemory_XPROG_Params.Length)))
		{
			ReturnStatus = XPROG_ERR_TIMEOUT;
		}
	}

	Endpoint_Write_8(CMD_XPROG);
	Endpoint_Write_8(XPROG_CMD_WRITE_MEM);
	Endpoint_Write_8(ReturnStatus);
	Endpoint_ClearIN();
}