+ \r
+ TMC_MessageHeader_t MessageHeader;\r
+ uint16_t BytesTransferred;\r
+ \r
+ /* Try to read in a TMC message from the interface, process if one is available */\r
+ if (ReadTMCHeader(&MessageHeader))\r
+ {\r
+ /* Indicate busy */\r
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
+ \r
+ switch (MessageHeader.MessageID)\r
+ {\r
+ case TMC_MESSAGEID_DEV_DEP_MSG_OUT:\r
+ BytesTransferred = 0;\r
+ while (Endpoint_Discard_Stream(MessageHeader.TransferSize, &BytesTransferred) ==\r
+ ENDPOINT_RWSTREAM_IncompleteTransfer)\r
+ {\r
+ if (IsTMCBulkOUTReset)\r
+ break;\r
+ }\r
+ LastTransferLength = BytesTransferred;\r
+ \r
+ Endpoint_ClearOUT();\r
+ break;\r
+ case TMC_MESSAGEID_DEV_DEP_MSG_IN:\r
+ Endpoint_ClearOUT();\r
+ \r
+ char MessageData[] = "TMC Class Test";\r
+\r
+ MessageHeader.TransferSize = strlen(MessageData);\r
+ MessageHeader.MessageIDSpecific.DeviceOUT.LastMessageTransaction = true;\r
+ WriteTMCHeader(&MessageHeader);\r
+\r
+ BytesTransferred = 0;\r
+ while (Endpoint_Write_Stream_LE(MessageData, MessageHeader.TransferSize, &BytesTransferred) ==\r
+ ENDPOINT_RWSTREAM_IncompleteTransfer)\r
+ {\r
+ if (IsTMCBulkINReset)\r
+ break;\r
+ }\r
+ LastTransferLength = BytesTransferred;\r
+\r
+ Endpoint_ClearIN();\r
+ break;\r
+ default:\r
+ Endpoint_StallTransaction();\r
+ break;\r
+ }\r
+\r
+ LEDs_SetAllLEDs(LEDMASK_USB_READY);\r
+ }\r
+ \r
+ /* All pending data has been processed - reset the data abort flags */\r
+ IsTMCBulkINReset = false;\r
+ IsTMCBulkOUTReset = false;\r
+}\r
+\r
+/** Attempts to read in the TMC message header from the TMC interface.\r
+ *\r
+ * \param[out] MessageHeader Pointer to a location where the read header (if any) should be stored\r
+ *\r
+ * \return Boolean true if a header was read, false otherwise\r
+ */\r
+bool ReadTMCHeader(TMC_MessageHeader_t* const MessageHeader)\r
+{\r
+ uint16_t BytesTransferred;\r
+ uint8_t ErrorCode;\r
+\r
+ /* Select the Data Out endpoint */\r
+ Endpoint_SelectEndpoint(TMC_OUT_EPNUM);\r
+ \r
+ /* Abort if no command has been sent from the host */\r
+ if (!(Endpoint_IsOUTReceived()))\r
+ return false;\r
+ \r
+ /* Read in the header of the command from the host */\r
+ BytesTransferred = 0;\r
+ while ((ErrorCode = Endpoint_Read_Stream_LE(MessageHeader, sizeof(TMC_MessageHeader_t), &BytesTransferred)) ==\r
+ ENDPOINT_RWSTREAM_IncompleteTransfer)\r
+ {\r
+ if (IsTMCBulkOUTReset)\r
+ break;\r
+ }\r
+\r
+ /* Store the new command tag value for later use */\r
+ CurrentTransferTag = MessageHeader->Tag;\r
+ \r
+ /* Indicate if the command has been aborted or not */\r
+ return (!(IsTMCBulkOUTReset) && (ErrorCode == ENDPOINT_RWSTREAM_NoError));\r
+}\r
+\r
+bool WriteTMCHeader(TMC_MessageHeader_t* const MessageHeader)\r
+{\r
+ uint16_t BytesTransferred;\r
+ uint8_t ErrorCode;\r
+\r
+ /* Set the message tag of the command header */\r
+ MessageHeader->Tag = CurrentTransferTag;\r
+ MessageHeader->InverseTag = ~CurrentTransferTag;\r
+\r
+ /* Select the Data In endpoint */\r
+ Endpoint_SelectEndpoint(TMC_IN_EPNUM);\r
+\r
+ /* Send the command header to the host */\r
+ BytesTransferred = 0;\r
+ while ((ErrorCode = Endpoint_Write_Stream_LE(MessageHeader, sizeof(TMC_MessageHeader_t), &BytesTransferred)) ==\r
+ ENDPOINT_RWSTREAM_IncompleteTransfer)\r
+ {\r
+ if (IsTMCBulkINReset)\r
+ break;\r
+ }\r
+\r
+ /* Indicate if the command has been aborted or not */\r
+ return (!(IsTMCBulkINReset) && (ErrorCode == ENDPOINT_RWSTREAM_NoError));\r