diff options
Diffstat (limited to 'mcc_generated_files/usb/usb_peripheral')
7 files changed, 4299 insertions, 0 deletions
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral.c b/mcc_generated_files/usb/usb_peripheral/usb_peripheral.c new file mode 100644 index 0000000..bdaaf92 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral.c @@ -0,0 +1,646 @@ +/**
+ * USBPERIPHERAL Peripheral Source File
+ * @file usb_peripheral.c
+ * @ingroup usb_peripheral
+ * @brief Interface for a usb_peripheral module that needs to be implemented by a device specific USB module driver.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+(c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+Subject to your compliance with these terms, you may use Microchip software and any
+derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+license terms applicable to your use of third party software (including open source software) that
+may accompany Microchip software.
+
+THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+FOR A PARTICULAR PURPOSE.
+
+IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+SOFTWARE.
+*/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <usb_common_elements.h>
+#include <usb_config.h>
+#include <usb_peripheral.h>
+#include <usb_peripheral_avr_du.h>
+#include <usb_protocol_headers.h>
+
+STATIC USB_CONTROL_TRANSFER_t controlTransfer __attribute__((aligned(2))) = { .transferDataPtr = controlTransfer.buffer };
+
+bool USB_SetupIsReceived(void)
+{
+ return USB_SetupInterruptIs();
+}
+
+bool USB_EventSOFIsReceived(void)
+{
+ return USB_SOFInterruptIs();
+}
+
+void USB_EventSOFClear(void)
+{
+ USB_SOFInterruptClear();
+}
+
+bool USB_EventResetIsReceived(void)
+{
+ return USB_ResetInterruptIs();
+}
+
+void USB_EventResetClear(void)
+{
+ USB_ResetInterruptClear();
+}
+
+uint8_t USB_EventOverUnderflowIsReceived(void)
+{
+ uint8_t eventOverUnderflow = 0;
+ if (USB_OverflowInterruptIs() == true)
+ {
+ eventOverUnderflow |= (uint8_t)OVERFLOW_EVENT;
+ }
+ if (USB_UnderflowInterruptIs() == true)
+ {
+ eventOverUnderflow |= (uint8_t)UNDERFLOW_EVENT;
+ }
+ return eventOverUnderflow;
+}
+
+uint8_t USB_ControlOverUnderflowIsReceived(void)
+{
+ uint8_t eventOverUnderflow = 0;
+ if (USB_EndpointOutOverUnderflowIsSet(0) == true)
+ {
+ eventOverUnderflow |= (uint8_t)OVERFLOW_EVENT;
+ USB_EndpointOutOverUnderflowAck(0);
+ }
+ if (USB_EndpointInOverUnderflowIsSet(0) == true)
+ {
+ eventOverUnderflow |= (uint8_t)UNDERFLOW_EVENT;
+ USB_EndpointInOverUnderflowAck(0);
+ }
+ return eventOverUnderflow;
+}
+
+void USB_EventOverUnderflowClear(void)
+{
+ USB_OverflowInterruptClear();
+ USB_UnderflowInterruptClear();
+}
+
+bool USB_EventSuspendIsReceived(void)
+{
+ return USB_SuspendInterruptIs();
+}
+
+void USB_EventSuspendClear(void)
+{
+ USB_SuspendInterruptClear();
+}
+
+bool USB_EventResumeIsReceived(void)
+{
+ return USB_ResumeInterruptIs();
+}
+
+void USB_EventResumeClear(void)
+{
+ USB_ResumeInterruptClear();
+}
+
+bool USB_EventStalledIsReceived(void)
+{
+ return USB_StalledInterruptIs();
+}
+
+void USB_EventStalledClear(void)
+{
+ USB_StalledInterruptClear();
+}
+
+void USB_BusAttach(void)
+{
+ USB_ConnectionAttach();
+}
+
+void USB_BusDetach(void)
+{
+ USB_ConnectionDetach();
+}
+
+bool USB_IsBusAttached(void)
+{
+ return USB_ConnectionIsAttach();
+}
+
+void USB_DeviceAddressConfigure(uint8_t deviceAddress)
+{
+ USB_DeviceAddressSet(deviceAddress);
+}
+
+uint16_t USB_FrameNumberGet(void)
+{
+ return (USB_FrameNumGet());
+}
+
+RETURN_CODE_t USB_ControlEndpointsInit(void)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ USB_PIPE_t controlPipeOut = { .address = 0, .direction = USB_EP_DIR_OUT };
+ USB_PIPE_t controlPipeIn = { .address = 0, .direction = USB_EP_DIR_IN };
+
+ status = USB_EndpointConfigure(controlPipeOut, USB_EP0_SIZE, CONTROL);
+ if (SUCCESS == status)
+ {
+ status = USB_EndpointConfigure(controlPipeIn, USB_EP0_SIZE, CONTROL);
+ }
+
+ if (SUCCESS == status)
+ {
+ status = EndpointBufferSet(controlPipeOut, controlTransfer.buffer);
+ if (SUCCESS == status)
+ {
+ status = EndpointBufferSet(controlPipeIn, controlTransfer.buffer);
+ }
+ }
+
+ if (SUCCESS == status)
+ {
+ status = USB_DataToggleClear(controlPipeOut);
+ if (SUCCESS == status)
+ {
+ status = USB_DataToggleSet(controlPipeIn);
+ }
+ }
+
+ if (SUCCESS == status)
+ {
+ controlTransfer.status = USB_CONTROL_SETUP;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlSetupReceived(void)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ USB_SetupInterruptClear();
+
+ if (USB_CONTROL_STALL_REQ == controlTransfer.status)
+ {
+ // Stall events are handled by the EventHandler.
+ status = SUCCESS;
+ }
+ else
+ {
+ // Acks Setup Received on the control endpoints.
+ USB_EndpointOutSetupReceivedAck(0u);
+ USB_EndpointInSetupCompleteAck(0u);
+
+ // Clears bytes received and sent
+ USB_NumberBytesToSendReset(0u);
+ USB_NumberBytesSentReset(0u);
+ USB_NumberBytesToReceiveReset(0u);
+ USB_NumberBytesReceivedReset(0u);
+
+ // Copies setup packet out of buffer to make it available for a data stage.
+ (void)memcpy((uint8_t *)(&controlTransfer.setupRequest), controlTransfer.buffer, sizeof(USB_SETUP_REQUEST_t));
+
+ // The processSetupCallback is in most cases the USB_SetupProcess function in usb_core.c.
+ if (controlTransfer.processSetupCallback != NULL)
+ {
+ RETURN_CODE_t setup_status = controlTransfer.processSetupCallback(&controlTransfer.setupRequest);
+
+ if (UNSUPPORTED == setup_status)
+ {
+ // Setup Request unknown or rejected, stalls the next control transaction.
+ controlTransfer.status = USB_CONTROL_STALL_REQ;
+ USB_EndpointInStall(0u);
+ USB_EndpointOutStall(0u);
+
+ status = SUCCESS;
+ }
+ else if (SUCCESS == setup_status)
+ {
+ if (0u == controlTransfer.transferDataSize)
+ {
+ // Request did not contain a data stage, sends ZLP directly.
+ status = USB_ControlTransferZLP(USB_EP_DIR_IN);
+ }
+ else
+ {
+ // Sends or Receives data in next stage of request.
+ controlTransfer.totalBytesTransferred = 0;
+ USB_PIPE_t controlPipe = { .address = 0u, .direction = USB_EP_DIR_IN };
+ if ((controlTransfer.setupRequest.bmRequestType.dataPhaseTransferDirection) == USB_REQUEST_DIR_IN)
+ {
+ controlTransfer.status = USB_CONTROL_DATA_IN;
+ }
+ else
+ {
+ // Control OUT data transactions are controlled by the IN.DATAPTR so set specifically here.
+ status = EndpointBufferSet(controlPipe, controlTransfer.transferDataPtr);
+
+ controlPipe.direction = USB_EP_DIR_OUT;
+ controlTransfer.status = USB_CONTROL_DATA_OUT;
+ }
+
+ // Sets up the pipe variables.
+ USB_PipeDataTransferredSizeReset(controlPipe);
+ USB_PipeDataPtrSet(controlPipe, controlTransfer.transferDataPtr);
+ USB_PipeDataToTransferSizeSet(controlPipe, controlTransfer.transferDataSize);
+
+ // Start data stage transaction.
+ status = USB_ControlTransactionComplete(controlPipe);
+ }
+ }
+ else
+ {
+ // Forward error from setup.
+ status = setup_status;
+ }
+ }
+ else
+ {
+ // processSetupCallback missing, return error.
+ status = CONTROL_SETUP_CALLBACK_ERROR;
+ }
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlTransactionComplete(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (pipe.address != 0)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ // The data stage and the status stage must always have the data toggle bit set.
+ status = USB_DataToggleSet(pipe);
+ }
+
+ if (SUCCESS == status)
+ {
+ switch (controlTransfer.status)
+ {
+ case USB_CONTROL_DATA_IN:
+ {
+ pipe.direction = USB_EP_DIR_IN;
+
+ // Updates bytes sent and to be sent.
+ uint16_t bytesSent = USB_PipeDataTransferredSizeGet(pipe);
+ bytesSent += USB_NumberBytesSentGet(pipe.address);
+ USB_PipeDataTransferredSizeSet(pipe, bytesSent);
+ uint16_t transferDataSize = USB_PipeDataToTransferSizeGet(pipe);
+
+ // Checks remaining data to send.
+ if (0U == (transferDataSize - bytesSent))
+ {
+ controlTransfer.totalBytesTransferred += bytesSent;
+ if (controlTransfer.transferDataSize == controlTransfer.totalBytesTransferred)
+ {
+
+ // Data stage is complete, sends an OUT ZLP for status stage.
+ status = USB_ControlTransferZLP(USB_REQUEST_DIR_OUT);
+ }
+ else
+ {
+ // Data stage is not complete, checks if we need a new buffer.
+ if ((controlTransfer.overUnderRunCallback != NULL) && (SUCCESS == controlTransfer.overUnderRunCallback()))
+ {
+ USB_PipeDataTransferredSizeReset(pipe);
+ USB_PipeDataToTransferSizeSet(pipe, controlTransfer.transferDataSize);
+ }
+
+ // If no new buffer a normal in ZLP will get sent for the data stage.
+ status = USB_InTransactionRun(pipe);
+ }
+ }
+ else
+ {
+ // Starts next transaction in data stage.
+ status = USB_InTransactionRun(pipe);
+ }
+
+ USB_EndpointInOverUnderflowAck(0);
+
+ break;
+ }
+ case USB_CONTROL_DATA_OUT:
+ {
+ pipe.direction = USB_EP_DIR_OUT;
+
+ // Updates bytes received and to be received.
+ uint16_t bytesReceived = USB_PipeDataTransferredSizeGet(pipe);
+ bytesReceived += USB_NumberBytesReceivedGet(pipe.address);
+ USB_PipeDataTransferredSizeSet(pipe, bytesReceived);
+ uint16_t transferDataSize = USB_PipeDataToTransferSizeGet(pipe);
+
+ if (0U == (transferDataSize - bytesReceived))
+ {
+ controlTransfer.totalBytesTransferred += bytesReceived;
+ if (controlTransfer.transferDataSize == controlTransfer.totalBytesTransferred)
+ {
+
+ // Data stage is complete, sends an IN ZLP for status stage.
+ status = USB_ControlTransferZLP(USB_REQUEST_DIR_IN);
+ }
+ else
+ {
+ // Data stage is not complete, checks if we need a new buffer.
+ if ((controlTransfer.overUnderRunCallback != NULL) && (SUCCESS == controlTransfer.overUnderRunCallback()))
+ {
+ USB_PipeDataTransferredSizeReset(pipe);
+ USB_PipeDataToTransferSizeSet(pipe, controlTransfer.transferDataSize);
+ status = USB_InTransactionRun(pipe);
+ }
+ else
+ {
+ // If no new buffer the next transaction will be stalled.
+ controlTransfer.status = USB_CONTROL_STALL_REQ;
+ USB_EndpointInStall(0);
+ USB_EndpointOutStall(0);
+
+ status = SUCCESS;
+ }
+ }
+ }
+ else
+ {
+ // Starts next transaction in data stage.
+ status = USB_OutTransactionRun(pipe);
+ }
+
+ USB_EndpointOutOverUnderflowAck(0);
+ break;
+ }
+ case USB_CONTROL_ZLP:
+ {
+ // Valid end of setup request.
+ if (controlTransfer.endOfRequestCallback != NULL)
+ {
+ controlTransfer.endOfRequestCallback();
+ }
+
+ // Reinitializes control endpoint management.
+ status = USB_ControlTransferReset();
+ break;
+ }
+ case USB_CONTROL_SETUP:
+ {
+ status = USB_ControlTransferReset();
+ break;
+ }
+ default:
+ {
+ status = CONTROL_TRANSACTION_STATUS_ERROR;
+ break;
+ }
+ }
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlTransferZLP(uint8_t direction)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ USB_NumberBytesToSendReset(0);
+ USB_NumberBytesSentReset(0);
+ USB_NumberBytesToReceiveReset(0u);
+ USB_NumberBytesReceivedReset(0u);
+
+ // Prepare to receive a new setup package in case the host decides to ignore the ZLP stage
+ USB_PipeDataPtrSet((USB_PIPE_t){ .address = 0, .direction = USB_REQUEST_DIR_OUT }, controlTransfer.buffer);
+ status = EndpointBufferSet((USB_PIPE_t){ .address = 0, .direction = USB_REQUEST_DIR_OUT }, controlTransfer.buffer);
+
+ if (SUCCESS == status)
+ {
+ controlTransfer.status = USB_CONTROL_ZLP;
+
+ // Starts the ZLP transaction
+ if (direction == USB_REQUEST_DIR_IN)
+ {
+ USB_EndpointInNAKClear(0);
+ USB_EndpointInOverUnderflowAck(0);
+ }
+ else
+ {
+ USB_EndpointOutNAKClear(0);
+ USB_EndpointOutOverUnderflowAck(0);
+ }
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlTransferReset(void)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+ USB_PIPE_t controlPipeOut = { .address = 0u, .direction = USB_EP_DIR_OUT };
+
+ // Aborts any ongoing transaction and resets the endpoint statuses
+ status = USB_TransactionAbort(controlPipeOut);
+ if (SUCCESS == status)
+ {
+ USB_PIPE_t controlPipeIn = { .address = 0u, .direction = USB_EP_DIR_IN };
+ status = USB_TransactionAbort(controlPipeIn);
+ }
+
+ if (SUCCESS == status)
+ {
+ USB_EndpointOutStatusClear(0u);
+ USB_EndpointInStatusClear(0u);
+
+ // Prepare for receiving a new request packet
+ USB_PipeDataPtrSet(controlPipeOut, controlTransfer.buffer);
+ USB_PipeDataToTransferSizeSet(controlPipeOut, sizeof(USB_SETUP_REQUEST_t));
+ USB_PipeDataTransferredSizeReset(controlPipeOut);
+ USB_PipeTransferEndCallbackRegister(controlPipeOut, NULL);
+
+ // Clears the endpoint count registers
+ USB_NumberBytesToSendReset(0u);
+ USB_NumberBytesSentReset(0u);
+ USB_NumberBytesToReceiveReset(0u);
+ USB_NumberBytesReceivedReset(0u);
+
+ // Resets the control transfer variables
+ controlTransfer.endOfRequestCallback = NULL;
+ controlTransfer.overUnderRunCallback = NULL;
+ controlTransfer.transferDataSize = 0u;
+ controlTransfer.status = USB_CONTROL_SETUP;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlTransferDataSet(uint8_t *dataPtr, uint16_t dataSize)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (dataPtr == NULL)
+ {
+ controlTransfer.transferDataPtr = controlTransfer.buffer;
+ if (0u != dataSize)
+ {
+ status = CONTROL_SIZE_ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ controlTransfer.transferDataPtr = dataPtr;
+ status = SUCCESS;
+ }
+ controlTransfer.transferDataSize = dataSize;
+
+ return status;
+}
+
+RETURN_CODE_t USB_ControlTransferDataWriteBuffer(uint8_t *dataPtr, uint8_t dataSize)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (USB_EP0_SIZE < dataSize)
+ {
+ status = CONTROL_SIZE_ERROR;
+ }
+ else
+ {
+ (void)memcpy(controlTransfer.buffer, dataPtr, dataSize);
+ controlTransfer.transferDataPtr = controlTransfer.buffer;
+ controlTransfer.transferDataSize = dataSize;
+
+ status = SUCCESS;
+ }
+ return status;
+}
+
+void USB_ControlEndOfRequestCallbackRegister(USB_SETUP_ENDOFREQUEST_CALLBACK_t callback)
+{
+ controlTransfer.endOfRequestCallback = callback;
+}
+
+void USB_ControlProcessSetupCallbackRegister(USB_SETUP_PROCESS_CALLBACK_t callback)
+{
+ controlTransfer.processSetupCallback = callback;
+}
+
+void USB_ControlOverUnderRunCallbackRegister(USB_SETUP_OVERUNDERRUN_CALLBACK_t callback)
+{
+ controlTransfer.overUnderRunCallback = callback;
+}
+
+RETURN_CODE_t USB_ControlProcessOverUnderflow(uint8_t overunderflow)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (USB_CONTROL_DATA_IN == controlTransfer.status)
+ {
+ if (OVERFLOW_EVENT == overunderflow)
+ {
+ // Host is done with the data stage and expects an OUT ZLP
+ status = USB_ControlTransferZLP(USB_REQUEST_DIR_OUT);
+ }
+ else
+ {
+ // Host is too eager, let this be handled by the transfer handler
+ status = SUCCESS;
+ }
+ }
+ else if (USB_CONTROL_DATA_OUT == controlTransfer.status)
+ {
+ if (UNDERFLOW_EVENT == overunderflow)
+ {
+ // Host is done with the data stage and expects an IN ZLP
+ status = USB_ControlTransferZLP(USB_REQUEST_DIR_IN);
+ }
+ else
+ {
+ // Host is too eager, let this be handled by the transfer handler
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ // Remaining control statuses ignores overflow and underflow events
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_HandleEventStalled(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ USB_EndpointInStallAck(pipe.address);
+ USB_EndpointOutStallAck(pipe.address);
+
+ USB_EndpointInStallClear(pipe.address);
+ USB_EndpointOutStallClear(pipe.address);
+
+ if (0u == pipe.address)
+ {
+ // Reinitializes control endpoint management.
+ status = USB_ControlTransferReset();
+ }
+ else
+ {
+ status = USB_TransactionAbort(pipe);
+ }
+
+ return status;
+}
+
+void USB_PeripheralInitialize(void)
+{
+ USB_Enable();
+ USB_FrameNumEnable();
+ USB_FifoEnable();
+ USB_FifoReadPointerReset();
+ USB_FifoWritePointerReset();
+ USB_EndpointTableAddressSet(endpointTable.EP);
+ USB_MaxEndpointsSet(USB_EP_NUM - 1u);
+ USB_InterruptFlagsClear();
+ // Reset endpoints table
+ for (uint8_t endpoint = 0; endpoint < (uint8_t)USB_EP_NUM; endpoint++)
+ {
+ endpointTable.EP[endpoint].OUT.CTRL = 0;
+ endpointTable.EP[endpoint].OUT.STATUS = 0;
+ endpointTable.EP[endpoint].IN.CTRL = 0;
+ endpointTable.EP[endpoint].IN.STATUS = 0;
+ }
+}
+
+void USB_PeripheralDisable(void)
+{
+ USB_Disable();
+ USB_DeviceAddressReset();
+}
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral.h b/mcc_generated_files/usb/usb_peripheral/usb_peripheral.h new file mode 100644 index 0000000..2957f60 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral.h @@ -0,0 +1,336 @@ +/**
+ * USBPERIPHERAL Peripheral Header File
+ * @file usb_peripheral.h
+ * @defgroup usb_peripheral USB Peripheral Hardware Abstraction Layer (HAL)
+ * @brief Interface for a USB peripheral module that needs to be implemented by a device-specific USB module driver.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#ifndef USB_PERIPHERAL_H
+// cppcheck-suppress misra-c2012-2.5
+#define USB_PERIPHERAL_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <usb_common_elements.h>
+#include <usb_peripheral_endpoint.h>
+#include <usb_peripheral_read_write.h>
+#include <usb_protocol_headers.h>
+
+/**
+ * @ingroup usb_peripheral
+ * @struct USB_CONTROL_TRANSFER_t
+ * @brief The data structure for internally handling control transfers, either IN or OUT.
+ */
+typedef struct USB_CONTROL_TRANSFER_struct
+{
+ uint8_t buffer[64]; /**<Default buffer for control data transfers*/
+ volatile USB_CONTROL_STATUS_t status; /**<The status of a transfer on this pipe*/
+ uint8_t *transferDataPtr; /**<Location in RAM to send or fill during transfer*/
+ uint16_t transferDataSize; /**<Number of bytes to transfer to or from RAM location*/
+ uint16_t totalBytesTransferred; /**<Number of data transfered last transaction*/
+ USB_SETUP_PROCESS_CALLBACK_t processSetupCallback; /**<Callback to call during setup process*/
+ USB_SETUP_OVERUNDERRUN_CALLBACK_t overUnderRunCallback; /**<Callback to call on a control overrun or underrun*/
+ USB_SETUP_ENDOFREQUEST_CALLBACK_t endOfRequestCallback; /**<Callback to call when a setup request is complete*/
+ USB_SETUP_REQUEST_t setupRequest; /**<Setup request packet*/
+} USB_CONTROL_TRANSFER_t;
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if the Setup event was received.
+ * @param None.
+ * @retval 0 - Setup event was not received
+ * @retval 1 - Setup event was received
+ */
+bool USB_SetupIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if the Start-of-Frame (SOF) event was received.
+ * @param None.
+ * @retval 0 - SOF event was not received
+ * @retval 1 - SOF event was received
+ */
+bool USB_EventSOFIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the SOF event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventSOFClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if the Reset event was received.
+ * @param None.
+ * @retval 1 - Reset event was received
+ * @retval 0 - Reset event was not received
+ */
+bool USB_EventResetIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the Reset event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventResetClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if an Overflow and/or Underflow event was received.
+ * @param None.
+ * @return A value representing the events received
+ */
+uint8_t USB_EventOverUnderflowIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if an Overflow and/or Underflow event was received on the control endpoints.
+ * @param None.
+ * @return A value representing the events received
+ */
+uint8_t USB_ControlOverUnderflowIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the Over/Underflow event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventOverUnderflowClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if a Suspend event was received.
+ * @param None.
+ * @return A boolean value representing the Suspend event received condition
+ * @retval 0 - Suspend event was not received
+ * @retval 1 - Suspend event was received
+ */
+bool USB_EventSuspendIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the Suspend event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventSuspendClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if a Resume event was received.
+ * @param None.
+ * @retval 0 - Resume event was not received
+ * @retval 1 - Resume event was received
+ */
+bool USB_EventResumeIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the Resume event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventResumeClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detects if a Stalled event was received.
+ * @param None.
+ * @retval 0 - Stalled event was not received
+ * @retval 1 - Stalled event was received
+ */
+bool USB_EventStalledIsReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Clears the Stalled event.
+ * @param None.
+ * @return None.
+ */
+void USB_EventStalledClear(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Attaches the device to the USB bus.
+ * @param None.
+ * @return None.
+ */
+void USB_BusAttach(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Detaches the device from the USB bus.
+ * @param None.
+ * @return None.
+ */
+void USB_BusDetach(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Checks if the device is attached to the USB bus not.
+ * @param None.
+ * @retval 0 - USB bus is not attached
+ * @retval 1 - USB bus is attached
+ */
+bool USB_IsBusAttached(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Sets the device address.
+ * @param deviceAddress - Device address to set
+ * @return None.
+ */
+void USB_DeviceAddressConfigure(uint8_t deviceAddress);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Gets the current frame number.
+ * @param None.
+ * @return 15-bit frame number
+ */
+uint16_t USB_FrameNumberGet(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Ensures correct control endpoint initialization.
+ * @param None.
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlEndpointsInit(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Verifies the received control setup.
+ * @param None.
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlSetupReceived(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Handles completed transactions on the control endpoints. Checks and verifies data OUT, data IN, ZLP OUT and ZLP IN.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlTransactionComplete(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Sends ZLP OUT and ZLP IN transactions on the control endpoints.
+ * @param direction - The endpoint direction to send the ZLP
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlTransferZLP(uint8_t direction);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Ensures correct control transfer reset.
+ * @param None.
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlTransferReset(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Updates the transfer data pointer and size in ControlTransfer.
+ * @param *dataPtr - Pointer to new data
+ * @param dataSize - Number of elements in the array
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlTransferDataSet(uint8_t *dataPtr, uint16_t dataSize);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Copies data to the transfer buffer and sets the transfer data pointer and size in ControlTransfer.
+ * @param *dataPtr - Pointer to data to copy
+ * @param dataSize - Number of elements in the array
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlTransferDataWriteBuffer(uint8_t *dataPtr, uint8_t dataSize);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Sets the callback for end of a control request.
+ * @param callback - The function to call for the end of a control request
+ * @return None.
+ */
+void USB_ControlEndOfRequestCallbackRegister(USB_SETUP_ENDOFREQUEST_CALLBACK_t callback);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Sets the callback for the setup processing.
+ * @param callback - The function to call for the setup processing
+ * @return None.
+ */
+void USB_ControlProcessSetupCallbackRegister(USB_SETUP_PROCESS_CALLBACK_t callback);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Sets the callback for a control overrun or underrun.
+ * @param callback - The function to call on a control overrun or underrun
+ * @return None.
+ */
+void USB_ControlOverUnderRunCallbackRegister(USB_SETUP_OVERUNDERRUN_CALLBACK_t callback);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Handles the control Over/Underflow events.
+ * @param overunderflow - A value representing overflow or underflow
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_ControlProcessOverUnderflow(uint8_t overunderflow);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Handles the Stall events.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_HandleEventStalled(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Enables the peripheral and the frame number, enables and resets FIFO, sets the endpoint table address and max endpoints.
+ * @param None.
+ * @return None.
+ */
+void USB_PeripheralInitialize(void);
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Disables the USB peripheral and aborts any ongoing transaction.
+ * @param None.
+ * @return None.
+ */
+void USB_PeripheralDisable(void);
+
+#endif /* USB_PERIPHERAL_H */
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral_avr_du.h b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_avr_du.h new file mode 100644 index 0000000..f0d8426 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_avr_du.h @@ -0,0 +1,1930 @@ +/**
+ * USBPERIPHERALAVRDU Peripheral AVR DU Specific Header File
+ * @file usb_peripheral_avr_du.h
+ * @defgroup usb_peripheral_avr_du USB Peripheral AVR DU
+ * @ingroup usb_peripheral
+ * @brief This file encompasses all the register settings of the AVR DU device in the form of inline functions.
+ * It also abstracts the Read-Modify-Write loop for STATUS registers, which is required, as the hardware and software can both write
+ * into the STATUS register.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#ifndef USB_PERIPHERAL_AVR_DU_H
+// cppcheck-suppress misra-c2012-2.5
+#define USB_PERIPHERAL_AVR_DU_H
+
+#ifdef __XC8
+ #include <xc.h>
+#else // avr-gcc
+ #include <avr/io.h>
+#endif
+
+#include <usb_config.h>
+#include <usb_protocol_headers.h>
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @def ALWAYS_INLINE
+ * @brief Alias that makes always inline function definitions more readable.
+ */
+#define ALWAYS_INLINE __attribute__((always_inline)) inline
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @struct USB_ENDPOINT_TABLE_struct
+ * @brief Represents the endpoint configuration table based on the number of endpoints in use.
+ * The table data structure is defined by USB_EP_TABLE_struct in the device header file,
+ * modified to support configuration of size from USB_EP_NUM.
+ */
+typedef struct USB_ENDPOINT_TABLE_struct
+{
+ register8_t FIFO[USB_EP_NUM * 2u]; /**<FIFO Entry*/
+ USB_EP_PAIR_t EP[USB_EP_NUM]; /**<USB Endpoint Register Pairs*/
+ register16_t FRAMENUM; /**<Frame Number*/
+} USB_ENDPOINT_TABLE_t;
+
+extern USB_ENDPOINT_TABLE_t endpointTable;
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @struct USB_PIPE_TRANSFER_struct
+ * @brief Represents a transfer created for a pipe, either IN or OUT.
+ */
+typedef struct USB_PIPE_TRANSFER_struct
+{
+ USB_TRANSFER_STATUS_t status; /**<The status of a transfer on this pipe*/
+ uint8_t ZLPEnable : 1; /**<A Zero Length Packet (ZLP) is enabled for the end of this transfer if the transfer size is a multiple of endpoint size */
+ uint8_t reserved : 7; /**<These bits are unused*/
+ uint8_t *transferDataPtr; /**<Location in RAM to send or fill during transfer*/
+ uint16_t transferDataSize; /**<Number of bytes to transfer to or from the RAM location*/
+ uint16_t bytesTransferred; /**<Total number of data transfered*/
+ USB_TRANSFER_END_CALLBACK_t transferEndCallback; /**<Callback to call at the end of transfer when transfer_data_size == bytes_transfered, NULL if not used*/
+} USB_PIPE_TRANSFER_t;
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Waits until a Read-Modify-Write operation is done.
+ * This blocking wait operation is expected to complete within 14 clock cycles.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void WaitUntilRMWDone(void)
+{
+ while ((USB0.INTFLAGSB & USB_RMWBUSY_bm) != 0u)
+ {
+ ;
+ }
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the OUT endpoint with the given address.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndPointOutDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL &= (~USB_TYPE_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the IN endpoint with the given address.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndPointInDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL &= (~USB_TYPE_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the OUT endpoint at the given address is enabled.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 Endpoint not enabled
+ * @retval 1 Endpoint enabled
+ */
+static ALWAYS_INLINE bool USB_EndPointOutIsEnabled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.CTRL & USB_TYPE_gm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the IN endpoint at the given address is enabled.
+ * @param None.
+ * @retval 0 Endpoint not enabled
+ * @retval 1 Endpoint enabled
+ */
+static ALWAYS_INLINE bool USB_EndPointInIsEnabled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.CTRL & USB_TYPE_gm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the OUT endpoint configuration at the given address.
+ * @param endpointAddress - Address of the endpoint
+ * @return Endpoint configuration type
+ */
+static ALWAYS_INLINE uint8_t USB_EndPointOutTypeConfigGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].OUT.CTRL & USB_TYPE_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the IN endpoint configuration at the given address.
+ * @param endpointAddress - Address of the endpoint
+ * @return Endpoint configuration type
+ */
+static ALWAYS_INLINE uint8_t USB_EndPointInTypeConfigGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].IN.CTRL & USB_TYPE_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets endpoint control OUT.
+ * @param endpointAddress - Address of the endpoint
+ * @param value - Register bitmask
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutControlSet(uint8_t endpointAddress, uint8_t value)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL = (value));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets endpoint control IN.
+ * @param endpointAddress - Address of the endpoint
+ * @param value - Register bitmask
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInControlSet(uint8_t endpointAddress, uint8_t value)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL = (value));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears OUT endpoint status.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutStatusClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = ~USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears IN endpoint status.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInStatusClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = ~USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the endpoint size for a default type OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param endpointSizeConfig - Size of endpoint to set
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutDefaultSizeSet(uint8_t endpointAddress, uint8_t endpointSizeConfig)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL = (endpointTable.EP[endpointAddress].OUT.CTRL & (~USB_BUFSIZE_DEFAULT_gm)) | ((endpointSizeConfig)&USB_BUFSIZE_DEFAULT_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the endpoint size for a default type IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param endpointSizeConfig - Size of endpoint to set
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInDefaultSizeSet(uint8_t endpointAddress, uint8_t endpointSizeConfig)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL = (endpointTable.EP[endpointAddress].IN.CTRL & (~USB_BUFSIZE_DEFAULT_gm)) | ((endpointSizeConfig)&USB_BUFSIZE_DEFAULT_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the endpoint size for an isochronous OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param endpointSizeConfig - Size of endpoint to set
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutIsoSizeSet(uint8_t endpointAddress, uint8_t endpointSizeConfig)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL = (endpointTable.EP[endpointAddress].OUT.CTRL & (~USB_BUFSIZE_ISO_gm)) | ((endpointSizeConfig)&USB_BUFSIZE_ISO_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the endpoint size for an isochronous IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param endpointSizeConfig - Size of endpoint to set
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInIsoSizeSet(uint8_t endpointAddress, uint8_t endpointSizeConfig)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL = (endpointTable.EP[endpointAddress].IN.CTRL & (~USB_BUFSIZE_ISO_gm)) | ((endpointSizeConfig)&USB_BUFSIZE_ISO_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the size of a default type OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return OUT endpoint size
+ */
+static ALWAYS_INLINE uint8_t USB_EndpointOutDefaultSizeGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].OUT.CTRL & USB_BUFSIZE_DEFAULT_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the size of a default type IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return IN endpoint size
+ */
+static ALWAYS_INLINE uint8_t USB_EndpointInDefaultSizeGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].IN.CTRL & USB_BUFSIZE_DEFAULT_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the size of an isochronous OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return OUT endpoint size
+ */
+static ALWAYS_INLINE uint8_t USB_EndpointOutIsoSizeGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].OUT.CTRL & USB_BUFSIZE_ISO_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the size of an isochronous IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return IN endpoint size
+ */
+static ALWAYS_INLINE uint8_t USB_EndpointInIsoSizeGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].IN.CTRL & USB_BUFSIZE_ISO_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables transaction complete interrupt for the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutTransactionCompleteInterruptEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL &= ~USB_TCDSBL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables transaction complete interrupt for the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInTransactionCompleteInterruptEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL &= ~USB_TCDSBL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables transaction complete interrupt for the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutTransactionCompleteInterruptDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL |= USB_TCDSBL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables transaction complete interrupt for the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInTransactionCompleteDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL |= USB_TCDSBL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables multipacket for the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutMultipktEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL |= USB_MULTIPKT_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables multipacket for the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInMultipktEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL |= USB_MULTIPKT_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables multipacket for the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutMultipktDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL &= ~USB_MULTIPKT_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables multipacket for the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInMultipktDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL &= ~USB_MULTIPKT_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if multipacket is enabled on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Multipacket disabled
+ * @retval 1 - Multipacket enabled
+ */
+static ALWAYS_INLINE bool USB_EndpointOutMultipktIsEnabled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.CTRL & USB_MULTIPKT_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if multipacket is enabled on the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Multipacket disabled
+ * @retval 1 - Multipacket enabled
+ */
+static ALWAYS_INLINE bool USB_EndpointInMultipktIsEnabled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.CTRL & USB_MULTIPKT_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables Auto Zero Length Packet (AZLP) on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutAzlpEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL |= USB_AZLP_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables AZLP on the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInAlzpEnable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL |= USB_AZLP_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables AZLP on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutAzlpDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL &= ~USB_AZLP_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables AZLP on the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInAzlpDisable(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL &= ~USB_AZLP_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Stalls the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutStall(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL |= USB_DOSTALL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Stalls the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInStall(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL |= USB_DOSTALL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Stops stalling the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutStallClear(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CTRL &= ~USB_DOSTALL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Stops stalling the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInStallClear(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.CTRL &= ~USB_DOSTALL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the specified OUT endpoint is stalled.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Endpoint is not stalled
+ * @retval 1 - Endpoint is stalled
+ */
+static ALWAYS_INLINE bool USB_EndpointOutIsStalled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.CTRL & USB_DOSTALL_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the specified IN endpoint is stalled.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Endpoint is not stalled
+ * @retval 1 - Endpoint is stalled
+ */
+static ALWAYS_INLINE bool USB_EndpointInIsStalled(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.CTRL & USB_DOSTALL_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges that an OUT endpoint is stalled and Clears the USB STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutStallAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_STALLED_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges that an IN endpoint is stalled and Clears the USB STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInStallAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_STALLED_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets OUT endpoint status to NAK.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutNAKSet(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTSET = USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets IN endpoint status to NAK.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInNAKSet(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INSET = USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB NAK status from the OUT endpoint STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutNAKClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB NAK status from the IN endpoint STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInNAKClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_BUSNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks the OUT endpoint STATUS register for the NAK status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Endpoint is not NAKed
+ * @retval 1 - Endpoint is NAKed
+ */
+static ALWAYS_INLINE bool USB_EndpointOutNAKIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_BUSNAK_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks the OUT endpoint STATUS register for the NAK status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Endpoint is not NAKed
+ * @retval 1 - Endpoint is NAKed
+ */
+static ALWAYS_INLINE bool USB_EndpointInNAKIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_BUSNAK_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges the transaction complete status on a specified OUT endpoint and Clears the USB STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutTransactionCompleteAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_TRNCOMPL_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges the transaction complete status on a specified IN endpoint and Clears the USB STATUS register.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInTransactionCompleteAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_TRNCOMPL_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB OUT endpoint has the Transaction Complete status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Transaction incomplete
+ * @retval 1 - Transaction complete
+ */
+static ALWAYS_INLINE bool USB_EndpointOutTransactionIsComplete(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_TRNCOMPL_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB IN endpoint has the Transaction Complete status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Transaction incomplete
+ * @retval 1 - Transaction complete
+ */
+static ALWAYS_INLINE bool USB_EndpointInTransactionIsComplete(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_TRNCOMPL_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges the Setup Received status on a specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutSetupReceivedAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_EPSETUP_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges the Setup Received status on a specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInSetupCompleteAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_EPSETUP_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB OUT endpoint has the Setup Received status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No setup received
+ * @retval 1 - Setup received
+ */
+static ALWAYS_INLINE bool USB_EndpointOutSetupIsReceived(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_EPSETUP_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB IN endpoint has the Setup Received status.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No setup received
+ * @retval 1 - Setup received
+ */
+static ALWAYS_INLINE bool USB_EndpointInSetupIsReceived(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_EPSETUP_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets OUT endpoint data toggle.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutDataToggleSet(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTSET = USB_TOGGLE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets IN endpoint data toggle.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInDataToggleSet(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INSET = USB_TOGGLE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears OUT endpoint data toggle.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutDataToggleClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_TOGGLE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears IN endpoint data toggle.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInDataToggleClear(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_TOGGLE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if data toggle is set on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Data toggle is not set
+ * @retval 1 - Data toggle is set
+ */
+static ALWAYS_INLINE bool USB_EndpointOutDataToggleIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_TOGGLE_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if data toggle is set on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - Data toggle is not set
+ * @retval 1 - Data toggle is set
+ */
+static ALWAYS_INLINE bool USB_EndpointInDataToggleIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_TOGGLE_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets endpoint buffer OUT.
+ * @param endpointAddress - Address of the endpoint
+ * @param bufAddress - Address pointer to buffer
+ * @return None.
+ * @misradeviation{@advisory, 11.4} A conversion should not be performed between a pointer to object and an integer type.
+ * The EP.OUT.DATAPTR register is a 16-bit register, expecting an AVR DU specific 16-bit RAM address.
+ */
+static ALWAYS_INLINE void USB_EndpointOutBufferSet(uint8_t endpointAddress, uint8_t *bufAddress)
+{
+ // cppcheck-suppress misra-c2012-11.4
+ endpointTable.EP[endpointAddress].OUT.DATAPTR = (uint16_t)bufAddress;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets endpoint buffer IN.
+ * @param endpointAddress - Address of the endpoint
+ * @param bufAddress - Address pointer to buffer
+ * @return None.
+ * @misradeviation{@advisory, 11.4} A conversion should not be performed between a pointer to object and an integer type.
+ * The EP.IN.DATAPTR register is a 16-bit register, expecting an AVR DU specific 16-bit RAM address.
+ */
+static ALWAYS_INLINE void USB_EndpointInBufferSet(uint8_t endpointAddress, uint8_t *bufAddress)
+{
+ // cppcheck-suppress misra-c2012-11.4
+ endpointTable.EP[endpointAddress].IN.DATAPTR = (uint16_t)bufAddress;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets how many bytes of data are intended to be sent from the specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param numberBytes - Amount of bytes to send
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesToSendSet(uint8_t endpointAddress, uint16_t numberBytes)
+{
+ (endpointTable.EP[endpointAddress].IN.CNT = (numberBytes));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Reads out the CNT register to know how many bytes of data are intended to be sent from the specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return Amount of bytes to send
+ */
+static ALWAYS_INLINE uint16_t USB_NumberBytesToSendGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].IN.CNT);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the CNT register to tell the peripheral no data is intended to be sent from the specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesToSendReset(uint8_t endpointAddress)
+{
+ USB_NumberBytesToSendSet(endpointAddress, 0x0000);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Reads out how many bytes have been sent from the specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return Amount of bytes that have been sent
+ */
+static ALWAYS_INLINE uint16_t USB_NumberBytesSentGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].IN.MCNT);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the MCNT register that keeps track of how many bytes of data have been sent.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesSentReset(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].IN.MCNT = (0x0000));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets how many bytes of data are expected to be received on a specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @param numberBytes - The amount of bytes to receive
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesToReceiveSet(uint8_t endpointAddress, uint16_t numberBytes)
+{
+ (endpointTable.EP[(endpointAddress)].OUT.MCNT = (numberBytes));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets how many bytes of data are expected to be received on a specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return Amount of bytes expected
+ */
+static ALWAYS_INLINE uint16_t USB_NumberBytesToReceiveGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].OUT.MCNT);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the MCNT register to tell the peripheral no data is intended to be received on the specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesToReceiveReset(uint8_t endpointAddress)
+{
+ USB_NumberBytesToReceiveSet(endpointAddress, 0x0000);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets how many bytes of data have been received on a specified endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return Amount of bytes expected
+ */
+static ALWAYS_INLINE uint16_t USB_NumberBytesReceivedGet(uint8_t endpointAddress)
+{
+ return (endpointTable.EP[endpointAddress].OUT.CNT);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Resets the counter that counts amount of bytes of data received on a specific endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_NumberBytesReceivedReset(uint8_t endpointAddress)
+{
+ (endpointTable.EP[endpointAddress].OUT.CNT = (0x0000));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if OUT endpoint has overflowed.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No overflow on endpoint
+ * @retval 1 - Overflow on endpoint
+ */
+static ALWAYS_INLINE bool USB_EndpointOutOverUnderflowIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_UNFOVF_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if IN endpoint has underflowed.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No underflow on endpoint
+ * @retval 1 - Undeflow on endpoint
+ */
+static ALWAYS_INLINE bool USB_EndpointInOverUnderflowIsSet(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_UNFOVF_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges overflow on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutOverUnderflowAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_UNFOVF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges underflow on the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInOverUnderflowAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_UNFOVF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the specified OUT endpoint has a Cyclic Redundancy Check (CRC) failure.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No CRC failure on endpoint
+ * @retval 1 - CRC failure on endpoint
+ */
+static ALWAYS_INLINE bool USB_EndpointOutCRCHasFailed(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].OUT.STATUS & USB_CRC_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the specified IN endpoint has a CRC failure.
+ * @param endpointAddress - Address of the endpoint
+ * @retval 0 - No CRC failure on endpoint
+ * @retval 1 - CRC failure on endpoint
+ */
+static ALWAYS_INLINE bool USB_EndpointInCRCHasFailed(uint8_t endpointAddress)
+{
+ return ((endpointTable.EP[endpointAddress].IN.STATUS & USB_CRC_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges a CRC failure on the specified OUT endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointOutCRCAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].OUTCLR = USB_CRC_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Acknowledges a CRC failure on the specified IN endpoint.
+ * @param endpointAddress - Address of the endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointInCRCAck(uint8_t endpointAddress)
+{
+ WaitUntilRMWDone();
+ USB0.STATUS[endpointAddress].INCLR = USB_CRC_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables global NAK.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_GlobalNAKEnable(void)
+{
+ USB0.CTRLB |= USB_GNAK_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables global NAK.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_GlobalNAKDisable(void)
+{
+ USB0.CTRLB &= ~(USB_GNAK_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks the global NAK setting.
+ * @param None.
+ * @retval 0 - Global NAK is disabled
+ * @retval 1 - Global NAK is enabled
+ */
+static ALWAYS_INLINE bool USB_GlobalNAKIsEnable(void)
+{
+ return ((USB0.CTRLB & USB_GNAK_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Tells the USB peripheral to attach.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ConnectionAttach(void)
+{
+ USB0.CTRLB |= USB_ATTACH_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Tells the USB peripheral to detach.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ConnectionDetach(void)
+{
+ USB0.CTRLB &= ~(USB_ATTACH_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB connection is attached.
+ * @param None.
+ * @retval 0 - USB connection is not attached
+ * @retval 1 - USB connection is attached
+ */
+static ALWAYS_INLINE bool USB_ConnectionIsAttach(void)
+{
+ return ((USB0.CTRLB & USB_ATTACH_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB peripheral.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_Enable(void)
+{
+ USB0.CTRLA |= USB_ENABLE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB peripheral.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_Disable(void)
+{
+ USB0.CTRLA &= ~(USB_ENABLE_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB peripheral is enabled.
+ * @param None.
+ * @retval 0 - USB peripheral not enabled
+ * @retval 1 - USB peripheral enabled
+ */
+static ALWAYS_INLINE bool USB_IsEnable(void)
+{
+ return ((USB0.CTRLA & USB_ENABLE_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables USB FIFO.
+ *
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FifoEnable(void)
+{
+ USB0.CTRLA |= USB_FIFOEN_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables USB FIFO.
+ *
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FifoDisable(void)
+{
+ USB0.CTRLA &= ~(USB_FIFOEN_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if USB FIFO has been enabled.
+ *
+ * This is a device-specific function.
+ * @param None.
+ * @retval 0 - USB FIFO is not enabled
+ * @retval 1 - USB FIFO is enabled
+ */
+static ALWAYS_INLINE bool USB_FifoIsEnable(void)
+{
+ return ((USB0.CTRLA & USB_FIFOEN_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables automatic global NAK for the USB peripheral.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_AutomaticGlobalNAKEnable(void)
+{
+ USB0.CTRLB |= USB_GNAUTO_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables automatic global NAK for the USB peripheral.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_AutomaticGlobalNAKDisable(void)
+{
+ USB0.CTRLB &= ~(USB_GNAUTO_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if automatic global NAK has been enabled.
+ * @param None.
+ * @retval 0 - Automatic global NAK is not enabled
+ * @retval 1 - Automatic global NAK is enabled
+ */
+static ALWAYS_INLINE bool USB_AutomaticGlobalNAKIsEnable(void)
+{
+ return ((USB0.CTRLB & USB_GNAUTO_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables storing the last SOF token frame number in FRAMENUM.
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FrameNumEnable(void)
+{
+ USB0.CTRLA |= USB_STFRNUM_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables storing the last SOF token frame number in FRAMENUM.
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FrameNumDisable(void)
+{
+ USB0.CTRLA &= ~(USB_STFRNUM_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if storing of the last SOF token frame number is enabled.
+ * This is a device-specific function.
+ * @param None.
+ * @retval 0 - Storing the last SOF token frame number in FRAMENUM is disabled
+ * @retval 1 - Storing the last SOF token frame number in FRAMENUM is enabled
+ */
+static ALWAYS_INLINE bool USB_FrameNumIsEnable(void)
+{
+ return ((USB0.CTRLA & USB_STFRNUM_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral
+ * @brief Gets the current frame number.
+ * @param None.
+ * @return 15-bit frame number
+ */
+static ALWAYS_INLINE uint16_t USB_FrameNumGet(void)
+{
+ return (endpointTable.FRAMENUM & USB_FRAMENUM_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets maximum number of endpoint addresses used by the USB peripheral.
+ * @param maxEndpoint - Last accessible endpoint
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_MaxEndpointsSet(uint8_t maxEndpoint)
+{
+ USB0.CTRLA = ((USB0.CTRLA & ~USB_MAXEP_gm) | (((maxEndpoint) << USB_MAXEP_gp) & USB_MAXEP_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB endpoint maximum, setting the maximum endpoint to EP0.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_MaxEndpointsReset(void)
+{
+ USB0.CTRLA &= ~(USB_MAXEP_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks what the maximum number of endpoint addresses is.
+ * @param None.
+ * @return Last accessible endpoint
+ */
+static ALWAYS_INLINE uint8_t USB_MaxEndpointsGet(void)
+{
+ return ((USB0.CTRLA & USB_MAXEP_gm) >> USB_MAXEP_gp);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the address of the endpoint table.
+ * This is a device-specific function.
+ * @param endpointTableAddress - Address of the endpoint table
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointTableAddressSet(USB_EP_PAIR_t *endpointTableAddress)
+{
+ USB0.EPPTR = (uint16_t)endpointTableAddress;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the address of the endpoint table to 0.
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_EndpointTableAddressReset(void)
+{
+ USB0.EPPTR = 0x0000;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the address of the endpoint table.
+ * This is a device-specific function.
+ * @param None.
+ * @return The address of the endpoint table
+ */
+static ALWAYS_INLINE uint16_t USB_EndpointTableAddressGet(void)
+{
+ return (USB0.EPPTR);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Resets the read FIFO pointer.
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FifoReadPointerReset(void)
+{
+ USB0.FIFORP |= (USB_FIFORP_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the read FIFO pointer.
+ * This is a device-specific function.
+ * @param None.
+ * @return The FIFO read pointer
+ */
+static ALWAYS_INLINE int8_t USB_FifoReadPointerGet(void)
+{
+ return (int8_t)(USB0.FIFORP);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Resets the write FIFO pointer.
+ * This is a device-specific function.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_FifoWritePointerReset(void)
+{
+ USB0.FIFOWP |= (USB_FIFOWP_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the write FIFO pointer.
+ * This is a device-specific function.
+ * @param None.
+ * @return The FIFO write pointer
+ */
+static ALWAYS_INLINE int8_t USB_FifoWritePointerGet(void)
+{
+ return (int8_t)(USB0.FIFOWP);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Sets the device address.
+ * @param usbAddress - The device address to set
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_DeviceAddressSet(uint8_t usbAddress)
+{
+ USB0.ADDR = ((USB0.ADDR & ~USB_ADDR_gm) | (((usbAddress) << USB_ADDR_gp) & USB_ADDR_gm));
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Resets the device address.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_DeviceAddressReset(void)
+{
+ USB0.ADDR &= ~(USB_ADDR_gm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the device address.
+ * @param None.
+ * @return The device address
+ */
+static ALWAYS_INLINE uint8_t USB_DeviceAddressGet(void)
+{
+ return ((USB0.ADDR & USB_ADDR_gm) >> USB_ADDR_gp);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables an upstream resume to be initated.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_UpstreamResumeEnable(void)
+{
+ USB0.CTRLB |= USB_URESUME_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if upstream resume is enabled, but not yet initiated.
+ * @param None.
+ * @retval 0 - Upstream resume initiated or not enabled
+ * @retval 1 - Upstream resume enabled
+ */
+static ALWAYS_INLINE bool USB_UpstreamResumeIsEnable(void)
+{
+ return ((USB0.CTRLB & USB_URESUME_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Gets the USB bus state.
+ * @param None.
+ * @return The state of the USB bus
+ */
+static ALWAYS_INLINE uint8_t USB_BusStateGet(void)
+{
+ return (USB0.BUSSTATE);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB bus has any specific status flags set.
+ * @param bus_state_bm - The bitmap of the specific status flags to check
+ * @retval 0 - No status flags set
+ * @retval 1 - The bus has one or more specified status flags set
+ */
+static ALWAYS_INLINE bool USB_BusStateIs(uint8_t bus_state_bm)
+{
+ return ((USB0.BUSSTATE & (bus_state_bm)) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Start-Of-Frame interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SOFInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_SOF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Start-Of-Frame interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SOFInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_SOF_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Start-Of-Frame Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SOFInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_SOF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Start-Of-Frame interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_SOFInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_SOF_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Suspend interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SuspendInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_SUSPEND_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Suspend interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SuspendInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_SUSPEND_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Suspend Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SuspendInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_SUSPEND_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Suspend interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_SuspendInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_SUSPEND_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Resume interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResumeInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_RESUME_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Resume interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResumeInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_RESUME_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Resume Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResumeInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_RESUME_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Resume interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_ResumeInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_RESUME_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Reset interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResetInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_RESET_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Reset interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResetInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_RESET_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Reset Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_ResetInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_RESET_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Reset interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_ResetInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_RESET_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Stalled interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_StalledInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_STALLED_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Stalled interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_StalledInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_STALLED_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Stalled Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_StalledInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_STALLED_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Stalled interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_StalledInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_STALLED_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Underflow interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_UnderflowInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_UNF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Underflow interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_UnderflowInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_UNF_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Underflow Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_UnderflowInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_UNF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if an Underflow interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_UnderflowInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_UNF_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Overflow interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_OverflowInterruptEnable(void)
+{
+ USB0.INTCTRLA |= USB_OVF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Overflow interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_OverflowInterruptDisable(void)
+{
+ USB0.INTCTRLA &= ~(USB_OVF_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Overflow Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_OverflowInterruptClear(void)
+{
+ USB0.INTFLAGSA = USB_OVF_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if an Overflow interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_OverflowInterruptIs(void)
+{
+ return ((USB0.INTFLAGSA & USB_OVF_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Transaction Complete interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_TransactionCompleteInterruptEnable(void)
+{
+ USB0.INTCTRLB |= USB_TRNCOMPL_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Transaction Complete interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_TransactionCompleteInterruptDisable(void)
+{
+ USB0.INTCTRLB &= ~(USB_TRNCOMPL_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Transaction Complete Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_TransactionCompleteInterruptAck(void)
+{
+ USB0.INTFLAGSB = USB_TRNCOMPL_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if a Transaction Complete interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_TransactionCompleteInterruptIs(void)
+{
+ return ((USB0.INTFLAGSB & USB_TRNCOMPL_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Read-Modify-Write Interrupt is enabled.
+ * @param None.
+ * @retval 0 - Interrupt not enabled
+ * @retval 1 - Interrupt enabled
+ */
+static ALWAYS_INLINE bool USB_ReadModifyWriteInterruptIs(void)
+{
+ return ((USB0.INTFLAGSB & USB_RMWBUSY_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Global NAK Done interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_GlobalNAKDoneInterruptEnable(void)
+{
+ USB0.INTCTRLB |= USB_GNDONE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Global NAK Done interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_GlobalNAKDoneInterruptDisable(void)
+{
+ USB0.INTCTRLB &= ~(USB_GNDONE_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Global NAK Done Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_GlobalNAKDoneInterruptAck(void)
+{
+ USB0.INTFLAGSB = USB_GNDONE_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if the USB Global NAK Done interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_GlobalNAKDoneInterruptIs(void)
+{
+ return ((USB0.INTFLAGSB & USB_GNDONE_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Enables the USB Setup interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SetupInterruptEnable(void)
+{
+ USB0.INTCTRLB |= USB_SETUP_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Disables the USB Setup interrupt.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SetupInterruptDisable(void)
+{
+ USB0.INTCTRLB &= ~(USB_SETUP_bm);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears the USB Setup Interrupt flag.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_SetupInterruptClear(void)
+{
+ USB0.INTFLAGSB = USB_SETUP_bm;
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Checks if a USB Setup interrupt has been triggered.
+ * @param None.
+ * @retval 0 - Interrupt not triggered
+ * @retval 1 - Interrupt triggered
+ */
+static ALWAYS_INLINE bool USB_SetupInterruptIs(void)
+{
+ return ((USB0.INTFLAGSB & USB_SETUP_bm) != 0u);
+}
+
+/**
+ * @ingroup usb_peripheral_avr_du
+ * @brief Clears all the USB Interrupt flags.
+ * @param None.
+ * @return None.
+ */
+static ALWAYS_INLINE void USB_InterruptFlagsClear(void)
+{
+ USB0.INTFLAGSA = 0xff;
+ USB0.INTFLAGSB = 0xff;
+}
+
+#endif /* USB_PERIPHERAL_AVR_DU_H */
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.c b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.c new file mode 100644 index 0000000..5ee9a21 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.c @@ -0,0 +1,510 @@ +/**
+ * USBPERIPHERALENDPOINT Peripheral Endpoint Source File
+ * @file usb_peripheral_endpoint.c
+ * @ingroup usb_peripheral_endpoint
+ * @brief API module for usb_peripheral covering endpoint related functions.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <usb_common_elements.h>
+#include <usb_config.h>
+#include <usb_peripheral_avr_du.h>
+#include <usb_peripheral_endpoint.h>
+#include <usb_protocol_headers.h>
+
+#if defined(USB_EP_NUM) && defined(USB_MAX_ENDPOINTS)
+ #if USB_EP_NUM > USB_MAX_ENDPOINTS
+ #error "USB_EP_NUM is too large, max is USB_MAX_ENDPOINTS"
+ #endif
+#else
+ #error "USB_EP_NUM not configured"
+#endif
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Algorithm to detect if a given number is a power of two.
+ * A number is a power of two if it has exactly one '1' in its binary representation. This is true if subtracting '1' from the number
+ * and doing an AND operation on the result with the number itself returns 0.
+ * @param number 8-bit unsigned integer
+ * @retval True - The given number is a power of two
+ * @retval False - The given number is not a power of two
+ */
+#define IsPowerOfTwo(number) ((0u != (number)) && (((number) & ((number)-1u)) == 0u))
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief SRAM tables for the FIFO and endpoint registers, as well as the FRAMENUM register.
+ * Represents the endpoint configuration table based on the number of endpoints in use.
+ * This line instantiates an object using the data structure type.
+ */
+USB_ENDPOINT_TABLE_t endpointTable __attribute__((aligned(2)));
+
+RETURN_CODE_t USB_EndpointConfigure(USB_PIPE_t pipe, uint16_t endpointSize, USB_ENDPOINT_t endpointType)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ uint8_t endpointConfiguration = 0;
+ if (SUCCESS != ConvertEndpointSizeToMask(endpointSize, endpointType, &endpointConfiguration))
+ {
+ status = ENDPOINT_SIZE_ERROR;
+ }
+ else if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else if (INTERRUPT < endpointType)
+ {
+ status = ENDPOINT_TYPE_ERROR;
+ }
+ else
+ {
+ switch (endpointType)
+ {
+ case CONTROL:
+ endpointConfiguration |= USB_TYPE_CONTROL_gc;
+ break;
+ case ISOCHRONOUS:
+ endpointConfiguration |= USB_TYPE_ISO_gc;
+ break;
+ case BULK:
+ case INTERRUPT:
+ endpointConfiguration |= USB_TYPE_BULKINT_gc;
+ break;
+ default:
+ endpointConfiguration |= USB_TYPE_DISABLE_gc;
+ break;
+ }
+
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutNAKSet(pipe.address);
+ USB_EndpointOutStatusClear(pipe.address);
+ USB_NumberBytesReceivedReset(pipe.address);
+ USB_EndpointOutControlSet(pipe.address, endpointConfiguration);
+
+ // Set up the static endpoint configurations
+ if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].OutMultipktEnable)
+ {
+ USB_EndpointOutMultipktEnable(pipe.address);
+
+ if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].OutAzlpEnable)
+ {
+ USB_EndpointOutAzlpEnable(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+ else if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].OutAzlpEnable)
+ {
+ // AZLP only works together with multipacket
+ status = ENDPOINT_AZLP_ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+
+ if ((uint8_t)0x01 != endpointStaticConfig[pipe.address].OutTrncInterruptEnable)
+ {
+ USB_EndpointOutTransactionCompleteInterruptDisable(pipe.address);
+ }
+ }
+ else
+ {
+ USB_EndpointInNAKSet(pipe.address);
+ USB_EndpointInStatusClear(pipe.address);
+ USB_NumberBytesToSendReset(pipe.address);
+ USB_EndpointInControlSet(pipe.address, endpointConfiguration);
+
+ // Set up the static endpoint configurations
+ if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].InMultipktEnable)
+ {
+ USB_EndpointInMultipktEnable(pipe.address);
+
+ if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].InAzlpEnable)
+ {
+ USB_EndpointInAlzpEnable(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+ else if ((uint8_t)0x01 == endpointStaticConfig[pipe.address].InAzlpEnable)
+ {
+ // AZLP only works together with multipacket
+ status = ENDPOINT_AZLP_ERROR;
+ }
+ else
+ {
+ status = SUCCESS;
+ }
+
+ if ((uint8_t)0x01 != endpointStaticConfig[pipe.address].InTrncInterruptEnable)
+ {
+ USB_EndpointInTransactionCompleteDisable(pipe.address);
+ }
+ }
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_EndpointDisable(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndPointOutDisable(pipe.address);
+ }
+ else
+ {
+ USB_EndPointInDisable(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+uint16_t USB_EndpointSizeGet(USB_PIPE_t pipe)
+{
+ uint8_t endpointType = 0;
+ uint8_t endpointSizeConfig = 0;
+ int16_t endpointSize = 0;
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ endpointType = USB_EndPointOutTypeConfigGet(pipe.address);
+ endpointSizeConfig = (USB_TYPE_ISO_gc == endpointType) ? USB_EndpointOutIsoSizeGet(pipe.address) : USB_EndpointOutDefaultSizeGet(pipe.address);
+ }
+ else
+ {
+ endpointType = USB_EndPointInTypeConfigGet(pipe.address);
+ endpointSizeConfig = (USB_TYPE_ISO_gc == endpointType) ? USB_EndpointInIsoSizeGet(pipe.address) : USB_EndpointInDefaultSizeGet(pipe.address);
+ }
+ if (USB_BUFSIZE_ISO_BUF1023_gc == endpointSizeConfig)
+ {
+ endpointSize = MAX_ENDPOINT_SIZE_ISO;
+ }
+ else
+ {
+ endpointSize = 8U << (uint16_t)endpointSizeConfig;
+ }
+ return endpointSize;
+}
+
+USB_ENDPOINT_t USB_EndpointTypeGet(USB_PIPE_t pipe)
+{
+ USB_TYPE_t endpointConfigType;
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ endpointConfigType = USB_EndPointOutTypeConfigGet(pipe.address);
+ }
+ else // USB_EP_DIR_IN
+ {
+ endpointConfigType = USB_EndPointInTypeConfigGet(pipe.address);
+ }
+
+ USB_ENDPOINT_t endpointType = DISABLED;
+ switch (endpointConfigType)
+ {
+ case USB_TYPE_CONTROL_gc:
+ endpointType = CONTROL;
+ break;
+ case USB_TYPE_BULKINT_gc:
+ // Peripheral does not distinguish between BULK and INTERRUPT, returning BULK
+ endpointType = BULK;
+ break;
+ case USB_TYPE_ISO_gc:
+ endpointType = ISOCHRONOUS;
+ break;
+ default:
+ // endpointType = DISABLED;
+ break;
+ }
+
+ return endpointType;
+}
+
+RETURN_CODE_t USB_EndpointStall(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutStall(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInStall(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_EndpointStallClear(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutStallClear(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInStallClear(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+bool USB_EndpointIsStalled(USB_PIPE_t pipe)
+{
+
+ bool isStalled = false;
+
+ if ((uint8_t)USB_EP_NUM > pipe.address)
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ isStalled = USB_EndpointOutIsStalled(pipe.address);
+ }
+ else
+ {
+ isStalled = USB_EndpointInIsStalled(pipe.address);
+ }
+ }
+
+ return isStalled;
+}
+
+RETURN_CODE_t USB_EndpointStalledConditionAck(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutStallAck(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInStallAck(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_DataToggleSet(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutDataToggleSet(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInDataToggleSet(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_DataToggleClear(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutDataToggleClear(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInDataToggleClear(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_DataToggle(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ (USB_EndpointOutDataToggleIsSet(pipe.address)) ? USB_DataToggleClear(pipe) : USB_DataToggleSet(pipe);
+ }
+ else
+ {
+ (USB_EndpointInDataToggleIsSet(pipe.address)) ? USB_DataToggleClear(pipe) : USB_DataToggleSet(pipe);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t ConvertEndpointSizeToMask(uint16_t endpointSize, USB_ENDPOINT_t endpointType, uint8_t *endpointMaskPtr)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (ISOCHRONOUS == endpointType)
+ {
+ if (((uint16_t)MAX_ENDPOINT_SIZE_ISO < endpointSize) || ((endpointSize < (uint16_t)MAX_ENDPOINT_SIZE_ISO) && !(IsPowerOfTwo(endpointSize))))
+ {
+ status = ENDPOINT_SIZE_ERROR;
+ }
+ }
+ else
+ {
+ if (((uint16_t)MAX_ENDPOINT_SIZE_DEFAULT < endpointSize) || !(IsPowerOfTwo(endpointSize)))
+ {
+ status = ENDPOINT_SIZE_ERROR;
+ }
+ }
+
+ if (UNINITIALIZED == status)
+ {
+ if ((uint16_t)MAX_ENDPOINT_SIZE_ISO == endpointSize)
+ {
+ *endpointMaskPtr = USB_BUFSIZE_ISO_BUF1023_gc;
+ }
+ else
+ {
+ uint8_t mask = 0;
+ uint16_t baseSize = 8;
+
+ while (baseSize < endpointSize)
+ {
+
+ mask++;
+ baseSize <<= 1;
+ }
+
+ *endpointMaskPtr = mask << USB_BUFSIZE_DEFAULT_gp;
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t EndpointBufferSet(USB_PIPE_t pipe, uint8_t *bufAddress)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ // Errata: Out transactions must be word aligned when using multipacket
+ if ((1u == endpointStaticConfig[pipe.address].OutMultipktEnable) && (((uint16_t)bufAddress & 0x0001) != 0u))
+ {
+ status = ENDPOINT_ALIGN_ERROR;
+ }
+ else
+ {
+ USB_EndpointOutBufferSet(pipe.address, bufAddress);
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ USB_EndpointInBufferSet(pipe.address, bufAddress);
+ status = SUCCESS;
+ }
+ }
+
+ return status;
+}
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.h b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.h new file mode 100644 index 0000000..fa77fca --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_endpoint.h @@ -0,0 +1,171 @@ +/**
+ * USBPERIPHERALENDPOINT Peripheral Endpoint Header File
+ * @file usb_peripheral_endpoint.h
+ * @defgroup usb_peripheral_endpoint USB Peripheral Endpoint
+ * @ingroup usb_peripheral
+ * @brief API module for usb_peripheral_endpoint covering endpoint-related functions.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#ifndef USB_PERIPHERAL_ENDPOINT_H
+// cppcheck-suppress misra-c2012-2.5
+#define USB_PERIPHERAL_ENDPOINT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "usb_common_elements.h"
+#include "usb_protocol_headers.h"
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Configures the endpoint with the desired settings using the Control and Status Register.
+ * Used to set up an endpoint before using it in an application.
+ * Sets up all the control register settings by looking up the usb_config.h file and clears the count registers.
+ * @param pipe - A combination of endpoint address and direction
+ * @param endpointSize - Number of bytes of data supported by the endpoint in one USB transaction
+ * @param endpointType - Type of USB endpoint as defined by usb_endpoint_type
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_EndpointConfigure(USB_PIPE_t pipe, uint16_t endpointSize, USB_ENDPOINT_t endpointType);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Disables the endpoint by setting the endpoint type to 0x00.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_EndpointDisable(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Helper function to return the endpoint size.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The size of the endpoint
+ */
+uint16_t USB_EndpointSizeGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Helper function to return the endpoint type.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The endpoint type
+ */
+USB_ENDPOINT_t USB_EndpointTypeGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Helps stall an endpoint when a command received from the host is invalid or unrecognizable.
+ * Used if the host sends data that is not supported by the device.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_EndpointStall(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Helps clear the Stall condition after the device has recovered from an unsupported command from the host.
+ * Used to reset stall before the next USB transfer.
+ * Used when the host issues a clear HALT/Feature request to reset stall.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_EndpointStallClear(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Helper function to return the endpoint Stall condition.
+ * @param pipe - A combination of endpoint address and direction
+ * @return A boolean value representing the Stall condition. If the pipe address is out of bounds, the function will always return false
+ */
+bool USB_EndpointIsStalled(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Acknowledges the stall status condition by clearing the Stall Status bit.
+ * Used to clear the Stall Status bit after a stall has been detected.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_EndpointStalledConditionAck(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Sets the Data Toggle bit on an endpoint which is used to ensure correct data sequence.
+ * Only used if hardware data toggling is not available.
+ * After a successful transaction, toggle the Data Toggle bit.
+ * For SETUP transactions, ensure that the SETUP stage clears the Data Toggle bit,
+ * while the data stage and status stage set the Data Toggle bit.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_DataToggleSet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Clears the Data Toggle bit on an endpoint which is used to ensure correct data sequence.
+ * Only used if hardware data toggling is not available.
+ * After a successful transaction, toggle the Data Toggle bit.
+ * For SETUP transactions, ensure that the SETUP stage clears the Data Toggle bit,
+ * while the data stage and status stage set the Data Toggle bit.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_DataToggleClear(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Toggles the Data Toggle bit on an endpoint which is used to ensure correct data sequence.
+ * Only used if hardware data toggling is not available.
+ * After a successful transaction, toggle the Data Toggle bit.
+ * For SETUP transactions, ensure that the SETUP stage clears the Data Toggle bit,
+ * while the data stage and status stage set the Data Toggle bit.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_DataToggle(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Converts an endpoint size in number of bytes into a register setting.
+ * Converts the endpoint size bit mask based on the EP_BUFSIZE setting of the endpoint control register.
+ * @param endpointSize - The size to convert
+ * @param endpointType - The endpoint type
+ * @param endpointMaskPtr - Pointer to the mask variable to write to
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t ConvertEndpointSizeToMask(uint16_t endpointSize, USB_ENDPOINT_t endpointType, uint8_t *endpointMaskPtr);
+
+/**
+ * @ingroup usb_peripheral_endpoint
+ * @brief Configures the endpoint data buffer to a location in RAM for the next transaction.
+ * @param pipe - A combination of endpoint address and direction
+ * @param bufAddress - The pointer to the data buffer the endpoint will use
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t EndpointBufferSet(USB_PIPE_t pipe, uint8_t *bufAddress);
+
+#endif /* USB_PERIPHERAL_ENDPOINT_H */
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.c b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.c new file mode 100644 index 0000000..1d91d08 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.c @@ -0,0 +1,484 @@ +/**
+ * USBPERIPHERALREADWRITE Peripheral Read/Write Source File
+ * @file usb_peripheral_read_write.c
+ * @ingroup usb_peripheral_read_write
+ * @brief API module for usb_peripheral covering low level USB transaction functions.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <usb_common_elements.h>
+#include <usb_config.h>
+#include <usb_peripheral_avr_du.h>
+#include <usb_peripheral_endpoint.h>
+#include <usb_peripheral_read_write.h>
+#include <usb_protocol_headers.h>
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @def Calculates from pipe address and direction to location in a transfer array.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The pipe transaction index for this pipe in pipe_transfer[]
+ */
+#define PipeTransferIndexGet(pipe) (((pipe).address * 2) + (pipe).direction)
+
+STATIC USB_PIPE_TRANSFER_t pipeTransfer[USB_EP_NUM * 2];
+
+RETURN_CODE_t USB_TransactionStart(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutNAKClear(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInNAKClear(pipe.address);
+ }
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_TransactionAbort(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutNAKSet(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInNAKSet(pipe.address);
+ }
+
+ pipeTransfer[PipeTransferIndexGet(pipe)].status = USB_PIPE_TRANSFER_ABORTED;
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_TransactionCompleteAck(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ if (USB_EP_DIR_OUT == pipe.direction)
+ {
+ USB_EndpointOutTransactionCompleteAck(pipe.address);
+ }
+ else
+ {
+ USB_EndpointInTransactionCompleteAck(pipe.address);
+ }
+ pipeTransfer[PipeTransferIndexGet(pipe)].status = USB_PIPE_TRANSFER_OK;
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+bool USB_TransactionIsCompleted(void)
+{
+ return USB_TransactionCompleteInterruptIs();
+}
+
+RETURN_CODE_t USB_TransactionCompletedPipeGet(USB_PIPE_t *pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (USB_TransactionIsCompleted())
+ {
+ // Finds FIFO entry by adding (subtracting) the signed read pointer to the size of the FIFO
+ // Reading the FIFO Read Pointer will handle the Transaction Complete Interrupt flag.
+ // The USB_FifoReadPointerGet is a device-specific function.
+
+ uint8_t fifoEntry = endpointTable.FIFO[(USB_EP_NUM * 2u) + USB_FifoReadPointerGet()];
+
+ // The FIFO entry contains the endpoint address and direction of the endpoint to handle next.
+ USB_PIPE_t returnPipe = { .direction = (fifoEntry & USB_DIR_bm) >> USB_DIR_bp, .address = (fifoEntry & USB_EPNUM_gm) >> USB_EPNUM_gp };
+
+ if ((uint8_t)USB_EP_NUM <= returnPipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ pipe->address = returnPipe.address;
+ pipe->direction = returnPipe.direction;
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ // No transaction is completed.
+ status = PIPE_TRANSFER_ERROR;
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_PipeReset(USB_PIPE_t pipe)
+{
+ RETURN_CODE_t status = UNINITIALIZED;
+ USB_PIPE_TRANSFER_t *pipeTransferPtr = &pipeTransfer[PipeTransferIndexGet(pipe)];
+
+ if ((uint8_t)USB_EP_NUM <= pipe.address)
+ {
+ status = ENDPOINT_ADDRESS_ERROR;
+ }
+ else
+ {
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_OK;
+ pipeTransferPtr->transferDataPtr = NULL;
+ pipeTransferPtr->transferDataSize = 0;
+ pipeTransferPtr->bytesTransferred = 0;
+ pipeTransferPtr->transferEndCallback = NULL;
+ pipeTransferPtr->ZLPEnable = false;
+
+ status = SUCCESS;
+ }
+
+ return status;
+}
+
+USB_TRANSFER_STATUS_t USB_PipeStatusGet(USB_PIPE_t pipe)
+{
+
+ return pipeTransfer[PipeTransferIndexGet(pipe)].status;
+}
+
+bool USB_PipeStatusIsBusy(USB_PIPE_t pipe)
+{
+
+ return (pipeTransfer[PipeTransferIndexGet(pipe)].status == USB_PIPE_TRANSFER_BUSY);
+}
+
+void USB_PipeDataPtrSet(USB_PIPE_t pipe, uint8_t *dataPtr)
+{
+
+ pipeTransfer[PipeTransferIndexGet(pipe)].transferDataPtr = dataPtr;
+}
+
+uint8_t *USB_PipeDataPtrGet(USB_PIPE_t pipe)
+{
+
+ return pipeTransfer[PipeTransferIndexGet(pipe)].transferDataPtr;
+}
+
+void USB_PipeDataToTransferSizeSet(USB_PIPE_t pipe, uint16_t dataSize)
+{
+
+ pipeTransfer[PipeTransferIndexGet(pipe)].transferDataSize = dataSize;
+}
+
+uint16_t USB_PipeDataToTransferSizeGet(USB_PIPE_t pipe)
+{
+
+ return pipeTransfer[PipeTransferIndexGet(pipe)].transferDataSize;
+}
+
+uint16_t USB_PipeDataTransferredSizeGet(USB_PIPE_t pipe)
+{
+
+ return pipeTransfer[PipeTransferIndexGet(pipe)].bytesTransferred;
+}
+
+void USB_PipeDataTransferredSizeSet(USB_PIPE_t pipe, uint16_t dataSize)
+{
+
+ pipeTransfer[PipeTransferIndexGet(pipe)].bytesTransferred = dataSize;
+}
+
+void USB_PipeDataTransferredSizeReset(USB_PIPE_t pipe)
+{
+
+ pipeTransfer[PipeTransferIndexGet(pipe)].bytesTransferred = 0;
+}
+
+void USB_PipeTransferZLP_Enable(USB_PIPE_t pipe)
+{
+ // Only enable manual ZLP if hardware AZLP is not enabled.
+ if (((USB_EP_DIR_IN == pipe.direction) && (0u == endpointStaticConfig[pipe.address].InAzlpEnable))
+ || ((USB_EP_DIR_OUT == pipe.direction) && (0u == endpointStaticConfig[pipe.address].OutAzlpEnable)))
+ {
+ pipeTransfer[PipeTransferIndexGet(pipe)].ZLPEnable = true;
+ }
+}
+
+void USB_PipeTransferEndCallbackRegister(USB_PIPE_t pipe, USB_TRANSFER_END_CALLBACK_t callback)
+{
+ pipeTransfer[PipeTransferIndexGet(pipe)].transferEndCallback = callback;
+}
+
+void USB_PipeTransferEndCallback(USB_PIPE_t pipe)
+{
+ USB_PIPE_TRANSFER_t *pipeTransferPtr = &pipeTransfer[PipeTransferIndexGet(pipe)];
+
+ if (NULL != pipeTransferPtr->transferEndCallback)
+ {
+ pipeTransferPtr->transferEndCallback(pipe, pipeTransferPtr->status, pipeTransferPtr->bytesTransferred);
+ }
+}
+
+RETURN_CODE_t USB_InTransactionRun(USB_PIPE_t pipe)
+{
+ USB_PIPE_TRANSFER_t *pipeTransferPtr = &pipeTransfer[PipeTransferIndexGet(pipe)];
+ RETURN_CODE_t status = UNINITIALIZED;
+ uint16_t nextTransactionSize;
+
+ if (USB_EP_DIR_IN != pipe.direction)
+ {
+ // Pipe is OUT, returns error code.
+ status = ENDPOINT_DIRECTION_ERROR;
+ }
+ else
+ {
+ // Makes sure the transfer status is busy.
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_BUSY;
+
+ // Calculates the size of next transaction.
+ nextTransactionSize = pipeTransferPtr->transferDataSize - pipeTransferPtr->bytesTransferred;
+ if (0U == nextTransactionSize)
+ {
+ // All data is sent, check if we need to send a manual ZLP as well.
+ if (true == pipeTransferPtr->ZLPEnable)
+ {
+ // Sends a zero-length package by setting bytes to send to 0.
+ USB_NumberBytesToSendSet(pipe.address, 0u);
+ USB_NumberBytesSentReset(pipe.address);
+ USB_EndpointInNAKClear(pipe.address);
+
+ // Clears ZLPEnable to show it has been sent.
+ pipeTransferPtr->ZLPEnable = false;
+ }
+ else
+ {
+ // Everything has been sent, return transfer status to OK.
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_OK;
+ }
+
+ status = SUCCESS;
+ }
+ else
+ {
+ uint16_t endpointSize = USB_EndpointSizeGet(pipe);
+ if ((0u == endpointStaticConfig[pipe.address].InMultipktEnable) && (nextTransactionSize > endpointSize))
+ {
+ // Only send endpoint size packet per transaction when MultiPacket is disabled.
+ nextTransactionSize = endpointSize;
+ }
+ else
+ {
+ // Check if a manual ZLP is needed after transaction, if transaction size is a multiple of endpoint size.
+ pipeTransferPtr->ZLPEnable = (pipeTransferPtr->ZLPEnable) && (0U == (nextTransactionSize % (uint16_t)endpointSize));
+ }
+
+ // Configure where to transfer from.
+ status = EndpointBufferSet(pipe, &pipeTransferPtr->transferDataPtr[pipeTransferPtr->bytesTransferred]);
+
+ // Send transaction
+ if (SUCCESS == status)
+ {
+ USB_NumberBytesToSendSet(pipe.address, nextTransactionSize);
+ USB_NumberBytesSentReset(pipe.address);
+ USB_EndpointInNAKClear(pipe.address);
+ }
+ }
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_OutTransactionRun(USB_PIPE_t pipe)
+{
+ USB_PIPE_TRANSFER_t *pipeTransferPtr = &pipeTransfer[PipeTransferIndexGet(pipe)];
+ RETURN_CODE_t status = UNINITIALIZED;
+
+ if (USB_EP_DIR_OUT != pipe.direction)
+ {
+ // Pipe is IN, return error code.
+ status = ENDPOINT_DIRECTION_ERROR;
+ }
+ else
+ {
+ // Make sure the transfer status is busy.
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_BUSY;
+
+ // Update the data pointer for the next transaction.
+ status = EndpointBufferSet(pipe, &pipeTransferPtr->transferDataPtr[pipeTransferPtr->bytesTransferred]);
+
+ // Calculate the size of next transaction.
+ uint16_t endpointSize = USB_EndpointSizeGet(pipe);
+ uint16_t nextTransactionSize = pipeTransferPtr->transferDataSize - pipeTransferPtr->bytesTransferred;
+ if (0u == endpointStaticConfig[pipe.address].OutMultipktEnable)
+ {
+ if (nextTransactionSize < endpointSize)
+ {
+ // Temporarily enable MultiPacket to avoid receiving data that overflows endpoint buffer.
+ USB_EndpointOutMultipktEnable(pipe.address);
+ }
+ else
+ {
+ // Only expect one endpoint size packet per transaction when MultiPacket is disabled.
+ if (nextTransactionSize > endpointSize)
+ {
+ nextTransactionSize = endpointSize;
+ }
+
+ // Disable MultiPacket in case it was enabled for previous transaction.
+ USB_EndpointOutMultipktDisable(pipe.address);
+ }
+ }
+
+ if (0u == nextTransactionSize)
+ {
+ // Clear ZLPEnable to indicate that the transfer is completed and the ZLP transfer is initated.
+ pipeTransferPtr->ZLPEnable = false;
+
+ // Everything has been sent, return transfer status to OK.
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_OK;
+ }
+ else
+ {
+ // Check if a manual ZLP is needed after transaction, if transaction size is a multiple of endpoint size.
+ pipeTransferPtr->ZLPEnable = pipeTransferPtr->ZLPEnable && (0u == (nextTransactionSize % endpointSize));
+ }
+
+ // Start the transaction
+ USB_NumberBytesReceivedReset(pipe.address);
+ USB_NumberBytesToReceiveSet(pipe.address, nextTransactionSize);
+ USB_EndpointOutNAKClear(pipe.address);
+ }
+
+ return status;
+}
+
+RETURN_CODE_t USB_PipeTransactionComplete(USB_PIPE_t pipe)
+{
+ USB_PIPE_TRANSFER_t *pipeTransferPtr = &pipeTransfer[PipeTransferIndexGet(pipe)];
+ RETURN_CODE_t status = UNINITIALIZED;
+ uint16_t transactionSize;
+
+ if (USB_EP_DIR_IN == pipe.direction)
+ {
+ // Transaction complete on IN.
+ if (USB_EndpointInMultipktIsEnabled(pipe.address) == true)
+ {
+ // With multipacket enabled we know exactly what got transferred.
+ transactionSize = USB_NumberBytesSentGet(pipe.address);
+ }
+ else
+ {
+ // With multipacket disabled we know what we meant to transfer.
+ transactionSize = USB_NumberBytesToSendGet(pipe.address);
+ }
+
+ // Check if we need to send more data, or ZLP.
+ pipeTransferPtr->bytesTransferred += transactionSize;
+ if ((pipeTransferPtr->bytesTransferred != pipeTransferPtr->transferDataSize) || (pipeTransferPtr->ZLPEnable))
+ {
+ status = USB_InTransactionRun(pipe);
+ }
+ else
+ {
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_OK;
+ status = SUCCESS;
+ }
+ }
+ else
+ {
+ // Transaction complete on OUT.
+ transactionSize = USB_NumberBytesReceivedGet(pipe.address);
+
+ // Checks if we have transferred more than we wanted.
+ uint16_t expectedTransferRemainingSize = pipeTransferPtr->transferDataSize - pipeTransferPtr->bytesTransferred;
+ if (expectedTransferRemainingSize < transactionSize)
+ {
+ // We may have overflowed the receive location!
+ if (USB_NumberBytesToReceiveGet(pipe.address) == expectedTransferRemainingSize)
+ {
+ // Multipacket has limited what we received, even if transactionSize is larger.
+ transactionSize = expectedTransferRemainingSize;
+ }
+ else
+ {
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_ERROR;
+ status = PIPE_TRANSFER_ERROR;
+ }
+ }
+
+ if (PIPE_TRANSFER_ERROR != status)
+ {
+ // Updates bytes transfered and check if we need to run more transactions.
+ pipeTransferPtr->bytesTransferred += transactionSize;
+
+ if (((pipeTransferPtr->bytesTransferred < pipeTransferPtr->transferDataSize) || pipeTransferPtr->ZLPEnable) && (0u == (transactionSize % USB_EndpointSizeGet(pipe))))
+ {
+ status = USB_OutTransactionRun(pipe);
+ }
+ else
+ {
+ pipeTransferPtr->status = USB_PIPE_TRANSFER_OK;
+ status = SUCCESS;
+ }
+ }
+ }
+
+ // Checks if transfer is completed and cleans up.
+ if (USB_PIPE_TRANSFER_BUSY != pipeTransferPtr->status)
+ {
+ USB_PipeTransferEndCallback(pipe);
+ }
+
+ return status;
+}
diff --git a/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.h b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.h new file mode 100644 index 0000000..9c477c0 --- /dev/null +++ b/mcc_generated_files/usb/usb_peripheral/usb_peripheral_read_write.h @@ -0,0 +1,222 @@ +/**
+ * USBPERIPHERALREADWRITE Peripheral Read/Write Header File
+ * @file usb_peripheral_read_write.h
+ * @defgroup usb_peripheral_read_write USB Peripheral Read/Write
+ * @ingroup usb_peripheral
+ * @brief API module for usb_peripheral covering low-level USB transaction functions.
+ * @version USB Device Stack HAL Driver Version 1.0.0
+ */
+/*
+ (c) 2021 Microchip Technology Inc. and its subsidiaries.
+
+ Subject to your compliance with these terms, you may use Microchip software and any
+ derivatives exclusively with Microchip products. It is your responsibility to comply with third party
+ license terms applicable to your use of third party software (including open source software) that
+ may accompany Microchip software.
+
+ THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
+ EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY
+ IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS
+ FOR A PARTICULAR PURPOSE.
+
+ IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,
+ INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND
+ WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP
+ HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO
+ THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL
+ CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT
+ OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS
+ SOFTWARE.
+ */
+
+#ifndef USB_PERIPHERAL_READ_WRITE_H
+// cppcheck-suppress misra-c2012-2.5
+#define USB_PERIPHERAL_READ_WRITE_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "usb_common_elements.h"
+#include "usb_protocol_headers.h"
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Starts sending or receiving data on an endpoint by clearing BUSNACK.
+ * Used as a final step while setting up a transaction on the bus.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_TransactionStart(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Aborts the next transaction on an endpoint by setting BUSNACK.
+ * Used to stop exchanging data on an endpoint. The device will start NAKing requests from the host after calling this API.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_TransactionAbort(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Acknowledges the Transaction Complete status condition by clearing the Transaction Complete status bit.
+ * Used to clear the Transaction Complete status bit after a transaction has successfully completed.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_TransactionCompleteAck(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Helper function to return the endpoint transaction complete condition.
+ * @param None.
+ * @retval 0 - Transaction not complete or pipe address is out of bounds
+ * @retval 1 - Transaction is complete
+ */
+bool USB_TransactionIsCompleted(void);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Returns the pipe address and direction for the latest completed transaction.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_TransactionCompletedPipeGet(USB_PIPE_t *pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Resets the pipe.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_PipeReset(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Gets the current status of pipe.
+ * @param pipe - A combination of endpoint address and direction
+ * @return USB_PIPE_TRANSFER_OK or an Error code according to USB_TRANSFER_STATUS_t
+ */
+USB_TRANSFER_STATUS_t USB_PipeStatusGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Checks if the pipe status is busy.
+ * @param pipe - A combination of endpoint address and direction
+ * @retval 0 - Pipe status not busy
+ * @retval 1 - Pipe status is busy
+ */
+bool USB_PipeStatusIsBusy(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Configures the pointer for the data transfer in a given pipe.
+ * @param pipe - A combination of endpoint address and direction
+ * @param *dataPtr - The pointer to the data location
+ * @return None.
+ */
+void USB_PipeDataPtrSet(USB_PIPE_t pipe, uint8_t *dataPtr);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Gets the current data pointer for a given pipe.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The pointer to the data location
+ */
+uint8_t *USB_PipeDataPtrGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Sets the size of pipe data to transfer.
+ * @param pipe - A combination of endpoint address and direction
+ * @param dataSize - The size of pipe data to transfer
+ * @return None.
+ */
+void USB_PipeDataToTransferSizeSet(USB_PIPE_t pipe, uint16_t dataSize);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Gets the size of pipe data to transfer.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The size of pipe data to transfer
+ */
+uint16_t USB_PipeDataToTransferSizeGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Gets the size of the transferred pipe data.
+ * @param pipe - A combination of endpoint address and direction
+ * @return The size of transferred pipe data
+ */
+uint16_t USB_PipeDataTransferredSizeGet(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Sets the size of the transferred pipe data.
+ * @param pipe - A combination of endpoint address and direction
+ * @param dataSize - The size of pipe data transferred
+ * @return None.
+ */
+void USB_PipeDataTransferredSizeSet(USB_PIPE_t pipe, uint16_t dataSize);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Resets the size of transferred pipe data.
+ * @param pipe - A combination of endpoint address and direction
+ * @return None.
+ */
+void USB_PipeDataTransferredSizeReset(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Enables a ZLP on a transfer.
+ * It is enabled by default if the AZLP static config is enabled for the pipe.
+ * @param pipe - A combination of endpoint address and direction
+ * @return None.
+ */
+void USB_PipeTransferZLP_Enable(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Sets the callback for transfer end.
+ * @param pipe - A combination of endpoint address and direction
+ * @param callback - A combination of pipe, status and transferred bytes
+ * @return None.
+ */
+void USB_PipeTransferEndCallbackRegister(USB_PIPE_t pipe, USB_TRANSFER_END_CALLBACK_t callback);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Calls the callback for transfer end.
+ * @param pipe - A combination of endpoint address and direction
+ * @return None.
+ */
+void USB_PipeTransferEndCallback(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Checks the correctness of IN transactions and runs them.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_InTransactionRun(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Checks the correctness OUT transactions and runs them.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_OutTransactionRun(USB_PIPE_t pipe);
+
+/**
+ * @ingroup usb_peripheral_read_write
+ * @brief Handles completed IN and OUT transactions.
+ * Processes the completed transaction and either completes the transfer or runs the next transaction.
+ * Will call the pipe transferEndCallback at the end of transfer, if configured.
+ * @param pipe - A combination of endpoint address and direction
+ * @return SUCCESS or an Error code according to RETURN_CODE_t
+ */
+RETURN_CODE_t USB_PipeTransactionComplete(USB_PIPE_t pipe);
+
+#endif /* USB_PERIPHERAL_READ_WRITE_H */
|
