- /* Pseudo-Function Macros: */
- #if defined(__DOXYGEN__)
- /** Indicates the number of bytes currently stored in the current pipes's selected bank.
- *
- * \note The return width of this function may differ, depending on the maximum pipe bank size
- * of the selected AVR model.
- *
- * \ingroup Group_PipeRW
- *
- * \return Total number of bytes in the currently selected Pipe's FIFO buffer
- */
- static inline uint16_t Pipe_BytesInPipe(void);
-
- /** Returns the pipe address of the currently selected pipe. This is typically used to save the
- * currently selected pipe number so that it can be restored after another pipe has been manipulated.
- *
- * \return Index of the currently selected pipe
- */
- static inline uint8_t Pipe_GetCurrentPipe(void);
-
- /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
- * indicated will operate on the currently selected pipe.
- *
- * \param[in] PipeNumber Index of the pipe to select
- */
- static inline void Pipe_SelectPipe(uint8_t PipeNumber);
-
- /** Resets the desired pipe, including the pipe banks and flags.
- *
- * \param[in] PipeNumber Index of the pipe to reset
- */
- static inline void Pipe_ResetPipe(uint8_t PipeNumber);
-
- /** Enables the currently selected pipe so that data can be sent and received through it to and from
- * an attached device.
- *
- * \note Pipes must first be configured properly via \ref Pipe_ConfigurePipe().
- */
- static inline void Pipe_EnablePipe(void);
-
- /** Disables the currently selected pipe so that data cannot be sent and received through it to and
- * from an attached device.
- */
- static inline void Pipe_DisablePipe(void);
-
- /** Determines if the currently selected pipe is enabled, but not necessarily configured.
- *
- * \return Boolean True if the currently selected pipe is enabled, false otherwise
- */
- static inline bool Pipe_IsEnabled(void);
-
- /** Gets the current pipe token, indicating the pipe's data direction and type.
- *
- * \return The current pipe token, as a PIPE_TOKEN_* mask
- */
- static inline uint8_t Pipe_GetPipeToken(void);
-
- /** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_*
- * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
- * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
- * which have two endpoints of opposite direction sharing the same endpoint address within the device.
- *
- * \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask
- */
- static inline void Pipe_SetPipeToken(uint8_t Token);
-
- /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
- static inline void Pipe_SetInfiniteINRequests(void);
-
- /** Configures the currently selected pipe to only allow the specified number of IN requests to be
- * accepted by the pipe before it is automatically frozen.
- *
- * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing
- */
- static inline void Pipe_SetFiniteINRequests(uint8_t TotalINRequests);
-
- /** Determines if the currently selected pipe is configured.
- *
- * \return Boolean true if the selected pipe is configured, false otherwise
- */
- static inline bool Pipe_IsConfigured(void);
-
- /** Retrieves the endpoint number of the endpoint within the attached device that the currently selected
- * pipe is bound to.
- *
- * \return Endpoint number the currently selected pipe is bound to
- */
- static inline uint8_t Pipe_BoundEndpointNumber(void);
-
- /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
- *
- * \param[in] Milliseconds Number of milliseconds between each pipe poll
- */
- static inline void Pipe_SetInterruptPeriod(uint8_t Milliseconds);
-
- /** Returns a mask indicating which pipe's interrupt periods have elapsed, indicating that the pipe should
- * be serviced.
- *
- * \return Mask whose bits indicate which pipes have interrupted
- */
- static inline uint8_t Pipe_GetPipeInterrupts(void);
-
- /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
- * pipes).
- *
- * \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested
- *
- * \return Boolean true if the specified pipe has interrupted, false otherwise
- */
- static inline bool Pipe_HasPipeInterrupted(uint8_t PipeNumber);
-
- /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
- static inline void Pipe_Unfreeze(void);
-
- /** Freezes the selected pipe, preventing it from communicating with an attached device. */
- static inline void Pipe_Freeze(void);
-
- /** Determines if the currently selected pipe is frozen, and not able to accept data.
- *
- * \return Boolean true if the currently selected pipe is frozen, false otherwise
- */
- static inline bool Pipe_IsFrozen(void);
-
- /** Clears the master pipe error flag. */
- static inline void Pipe_ClearError(void);
-
- /** Determines if the master pipe error flag is set for the currently selected pipe, indicating that
- * some sort of hardware error has occurred on the pipe.
- *
- * \see \ref Pipe_GetErrorFlags() macro for information on retrieving the exact error flag.
- *
- * \return Boolean true if an error has occurred on the selected pipe, false otherwise
- */
- static inline bool Pipe_IsError(void);
-
- /** Clears all the currently selected pipe's hardware error flags, but does not clear the master error
- * flag for the pipe.
- */
- static inline void Pipe_ClearErrorFlags(void);
-
- /** Gets a mask of the hardware error flags which have occurred on the currently selected pipe. This
- * value can then be masked against the PIPE_ERRORFLAG_* masks to determine what error has occurred.
- *
- * \return Mask comprising of PIPE_ERRORFLAG_* bits indicating what error has occurred on the selected pipe
- */
- static inline uint8_t Pipe_GetErrorFlags(void);
-
- /** Determines if the currently selected pipe may be read from (if data is waiting in the pipe
- * bank and the pipe is an IN direction, or if the bank is not yet full if the pipe is an OUT
- * direction). This function will return false if an error has occurred in the pipe, or if the pipe
- * is an IN direction and no packet (or an empty packet) has been received, or if the pipe is an OUT
- * direction and the pipe bank is full.
- *
- * \note This function is not valid on CONTROL type pipes.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if the currently selected pipe may be read from or written to, depending on its direction
- */
- static inline bool Pipe_IsReadWriteAllowed(void);
-
- /** Determines if an IN request has been received on the currently selected pipe.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if the current pipe has received an IN packet, false otherwise.
- */
- static inline bool Pipe_IsINReceived(void);
-
- /** Determines if the currently selected pipe is ready to send an OUT request.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if the current pipe is ready for an OUT packet, false otherwise.
- */
- static inline bool Pipe_IsOUTReady(void);
-
- /** Determines if no SETUP request is currently being sent to the attached device on the selected
- * CONTROL type pipe.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if the current pipe is ready for a SETUP packet, false otherwise.
- */
- static inline bool Pipe_IsSETUPSent(void);
-
- /** Sends the currently selected CONTROL type pipe's contents to the device as a SETUP packet.
- *
- * \ingroup Group_PipePacketManagement
- */
- static inline void Pipe_ClearSETUP(void);
-
- /** Acknowledges the reception of a setup IN request from the attached device on the currently selected
- * pipe, freeing the bank ready for the next packet.
- *
- * \ingroup Group_PipePacketManagement
- */
- static inline void Pipe_ClearIN(void);
-
- /** Sends the currently selected pipe's contents to the device as an OUT packet on the selected pipe, freeing
- * the bank ready for the next packet.
- *
- * \ingroup Group_PipePacketManagement
- */
- static inline void Pipe_ClearOUT(void);
-
- /** Determines if the device sent a NAK (Negative Acknowledge) in response to the last sent packet on
- * the currently selected pipe. This occurs when the host sends a packet to the device, but the device
- * is not currently ready to handle the packet (i.e. its endpoint banks are full). Once a NAK has been
- * received, it must be cleared using \ref Pipe_ClearNAKReceived() before the previous (or any other) packet
- * can be re-sent.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if an NAK has been received on the current pipe, false otherwise
- */
- static inline bool Pipe_IsNAKReceived(void);
-
- /** Clears the NAK condition on the currently selected pipe.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \see \ref Pipe_IsNAKReceived() for more details.
- */
- static inline void Pipe_ClearNAKReceived(void);
-
- /** Determines if the currently selected pipe has had the STALL condition set by the attached device.
- *
- * \ingroup Group_PipePacketManagement
- *
- * \return Boolean true if the current pipe has been stalled by the attached device, false otherwise
- */
- static inline bool Pipe_IsStalled(void);
-
- /** Clears the STALL condition detection flag on the currently selected pipe, but does not clear the
- * STALL condition itself (this must be done via a ClearFeature control request to the device).
- *
- * \ingroup Group_PipePacketManagement
- */
- static inline void Pipe_ClearStall(void);
- #else
- #define Pipe_BytesInPipe() UPBCX
-
- #define Pipe_GetCurrentPipe() (UPNUM & PIPE_PIPENUM_MASK)
-
- #define Pipe_SelectPipe(pipenum) MACROS{ UPNUM = (pipenum); }MACROE
-
- #define Pipe_ResetPipe(pipenum) MACROS{ UPRST = (1 << (pipenum)); UPRST = 0; }MACROE
-
- #define Pipe_EnablePipe() MACROS{ UPCONX |= (1 << PEN); }MACROE
-
- #define Pipe_DisablePipe() MACROS{ UPCONX &= ~(1 << PEN); }MACROE
-
- #define Pipe_IsEnabled() ((UPCONX & (1 << PEN)) ? true : false)
-
- #define Pipe_GetPipeToken() (UPCFG0X & PIPE_TOKEN_MASK)
-
- #define Pipe_SetPipeToken(token) MACROS{ UPCFG0X = ((UPCFG0X & ~PIPE_TOKEN_MASK) | (token)); }MACROE
-
- #define Pipe_SetInfiniteINRequests() MACROS{ UPCONX |= (1 << INMODE); }MACROE
-
- #define Pipe_SetFiniteINRequests(n) MACROS{ UPCONX &= ~(1 << INMODE); UPINRQX = (n); }MACROE
-
- #define Pipe_IsConfigured() ((UPSTAX & (1 << CFGOK)) ? true : false)
-
- #define Pipe_BoundEndpointNumber() ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK)
-
- #define Pipe_SetInterruptPeriod(ms) MACROS{ UPCFG2X = (ms); }MACROE
-
- #define Pipe_GetPipeInterrupts() UPINT
-
- #define Pipe_HasPipeInterrupted(n) ((UPINT & (1 << (n))) ? true : false)
-
- #define Pipe_Unfreeze() MACROS{ UPCONX &= ~(1 << PFREEZE); }MACROE
-
- #define Pipe_Freeze() MACROS{ UPCONX |= (1 << PFREEZE); }MACROE
-
- #define Pipe_IsFrozen() ((UPCONX & (1 << PFREEZE)) ? true : false)
-
- #define Pipe_ClearError() MACROS{ UPINTX &= ~(1 << PERRI); }MACROE
-
- #define Pipe_IsError() ((UPINTX & (1 << PERRI)) ? true : false)
-
- #define Pipe_ClearErrorFlags() MACROS{ UPERRX = 0; }MACROE
+ /* Enums: */
+ /** Enum for the possible error return codes of the Pipe_WaitUntilReady function.
+ *
+ * \ingroup Group_PipeRW
+ */
+ enum Pipe_WaitUntilReady_ErrorCodes_t
+ {
+ PIPE_READYWAIT_NoError = 0, /**< Pipe ready for next packet, no error. */
+ PIPE_READYWAIT_PipeStalled = 1, /**< The device stalled the pipe while waiting. */
+ PIPE_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while waiting. */
+ PIPE_READYWAIT_Timeout = 3, /**< The device failed to accept or send the next packet
+ * within the software timeout period set by the
+ * \ref USB_STREAM_TIMEOUT_MS macro.
+ */
+ };
+
+ /* Inline Functions: */
+ /** Indicates the number of bytes currently stored in the current pipes's selected bank.
+ *
+ * \note The return width of this function may differ, depending on the maximum pipe bank size
+ * of the selected AVR model.
+ *
+ * \ingroup Group_PipeRW
+ *
+ * \return Total number of bytes in the currently selected Pipe's FIFO buffer.
+ */
+ static inline uint16_t Pipe_BytesInPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint16_t Pipe_BytesInPipe(void)
+ {
+ return UPBCX;
+ }
+
+ /** Returns the pipe address of the currently selected pipe. This is typically used to save the
+ * currently selected pipe number so that it can be restored after another pipe has been manipulated.
+ *
+ * \return Index of the currently selected pipe.
+ */
+ static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetCurrentPipe(void)
+ {
+ return (UPNUM & PIPE_PIPENUM_MASK);
+ }
+
+ /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
+ * indicated will operate on the currently selected pipe.
+ *
+ * \param[in] PipeNumber Index of the pipe to select.
+ */
+ static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SelectPipe(const uint8_t PipeNumber)
+ {
+ UPNUM = PipeNumber;
+ }
+
+ /** Resets the desired pipe, including the pipe banks and flags.
+ *
+ * \param[in] PipeNumber Index of the pipe to reset.
+ */
+ static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_ResetPipe(const uint8_t PipeNumber)
+ {
+ UPRST = (1 << PipeNumber);
+ UPRST = 0;
+ }
+
+ /** Enables the currently selected pipe so that data can be sent and received through it to and from
+ * an attached device.
+ *
+ * \pre The currently selected pipe must first be configured properly via \ref Pipe_ConfigurePipe().
+ */
+ static inline void Pipe_EnablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_EnablePipe(void)
+ {
+ UPCONX |= (1 << PEN);
+ }
+
+ /** Disables the currently selected pipe so that data cannot be sent and received through it to and
+ * from an attached device.
+ */
+ static inline void Pipe_DisablePipe(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_DisablePipe(void)
+ {
+ UPCONX &= ~(1 << PEN);
+ }
+
+ /** Determines if the currently selected pipe is enabled, but not necessarily configured.
+ *
+ * \return Boolean True if the currently selected pipe is enabled, false otherwise.
+ */
+ static inline bool Pipe_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsEnabled(void)
+ {
+ return ((UPCONX & (1 << PEN)) ? true : false);
+ }
+
+ /** Gets the current pipe token, indicating the pipe's data direction and type.
+ *
+ * \return The current pipe token, as a PIPE_TOKEN_* mask.
+ */
+ static inline uint8_t Pipe_GetPipeToken(void) ATTR_ALWAYS_INLINE;
+ static inline uint8_t Pipe_GetPipeToken(void)
+ {
+ return (UPCFG0X & (0x03 << PTOKEN0));
+ }
+
+ /** Sets the token for the currently selected pipe to one of the tokens specified by the PIPE_TOKEN_*
+ * masks. This can be used on CONTROL type pipes, to allow for bidirectional transfer of data during
+ * control requests, or on regular pipes to allow for half-duplex bidirectional data transfer to devices
+ * which have two endpoints of opposite direction sharing the same endpoint address within the device.
+ *
+ * \param[in] Token New pipe token to set the selected pipe to, as a PIPE_TOKEN_* mask.
+ */
+ static inline void Pipe_SetPipeToken(const uint8_t Token) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetPipeToken(const uint8_t Token)
+ {
+ UPCFG0X = ((UPCFG0X & ~(0x03 << PTOKEN0)) | Token);
+ }
+
+ /** Configures the currently selected pipe to allow for an unlimited number of IN requests. */
+ static inline void Pipe_SetInfiniteINRequests(void) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetInfiniteINRequests(void)
+ {
+ UPCONX |= (1 << INMODE);
+ }
+
+ /** Configures the currently selected pipe to only allow the specified number of IN requests to be
+ * accepted by the pipe before it is automatically frozen.
+ *
+ * \param[in] TotalINRequests Total number of IN requests that the pipe may receive before freezing.
+ */
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests) ATTR_ALWAYS_INLINE;
+ static inline void Pipe_SetFiniteINRequests(const uint8_t TotalINRequests)
+ {
+ UPCONX &= ~(1 << INMODE);
+ UPINRQX = TotalINRequests;
+ }
+
+ /** Determines if the currently selected pipe is configured.
+ *
+ * \return Boolean true if the selected pipe is configured, false otherwise.
+ */
+ static inline bool Pipe_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
+ static inline bool Pipe_IsConfigured(void)
+ {
+ return ((UPSTAX & (1 << CFGOK)) ? true : false);
+ }