diff options
Diffstat (limited to 'LUFA/Drivers/USB')
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/Device.h | 62 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/Endpoint.h | 582 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/Host.h | 364 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/OTG.h | 130 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/Pipe.h | 710 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/USBController.h | 139 | ||||
-rw-r--r-- | LUFA/Drivers/USB/LowLevel/USBInterrupt.h | 11 |
7 files changed, 1137 insertions, 861 deletions
diff --git a/LUFA/Drivers/USB/LowLevel/Device.h b/LUFA/Drivers/USB/LowLevel/Device.h index c6c2e9fdd..2c9dc2810 100644 --- a/LUFA/Drivers/USB/LowLevel/Device.h +++ b/LUFA/Drivers/USB/LowLevel/Device.h @@ -50,11 +50,13 @@ #define __USBDEVICE_H__ /* Includes: */ + #include <avr/io.h> #include <avr/pgmspace.h> #include <avr/eeprom.h> #include "../../../Common/Common.h" #include "../HighLevel/StdDescriptors.h" + #include "USBInterrupt.h" #include "Endpoint.h" /* Preprocessor Checks: */ @@ -107,24 +109,6 @@ * \see \ref Group_Descriptors for more information on the RMWAKEUP feature and device descriptors. */ void USB_Device_SendRemoteWakeup(void); - - /* Pseudo-Function Macros: */ - #if defined(__DOXYGEN__) - /** Enables the device mode Start Of Frame events. When enabled, this causes the - * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus, - * at the start of each USB frame when enumerated in device mode. - */ - static inline bool USB_Device_EnableSOFEvents(void); - - /** Disables the device mode Start Of Frame events. When disabled, this stop the firing of the - * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode. - */ - static inline bool USB_Device_DisableSOFEvents(void); - #else - #define USB_Device_EnableSOFEvents() MACROS{ USB_INT_Enable(USB_INT_SOFI); }MACROE - - #define USB_Device_DisableSOFEvents() MACROS{ USB_INT_Disable(USB_INT_SOFI); }MACROE - #endif /* Type Defines: */ enum USB_Device_States_t @@ -155,6 +139,26 @@ */ }; + /* Inline Functions: */ + /** Enables the device mode Start Of Frame events. When enabled, this causes the + * \ref EVENT_USB_Device_StartOfFrame() event to fire once per millisecond, synchronized to the USB bus, + * at the start of each USB frame when enumerated in device mode. + */ + static inline void USB_Device_EnableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_EnableSOFEvents(void) + { + USB_INT_Enable(USB_INT_SOFI); + } + + /** Disables the device mode Start Of Frame events. When disabled, this stop the firing of the + * \ref EVENT_USB_Device_StartOfFrame() event when enumerated in device mode. + */ + static inline void USB_Device_DisableSOFEvents(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_DisableSOFEvents(void) + { + USB_INT_Disable(USB_INT_SOFI); + } + /* Function Prototypes: */ /** Function to retrieve a given descriptor's size and memory location from the given descriptor type value, * index and language ID. This function MUST be overridden in the user application (added with full, identical @@ -191,12 +195,26 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) - /* Macros: */ - #define USB_Device_SetLowSpeed() MACROS{ UDCON |= (1 << LSM); }MACROE - #define USB_Device_SetFullSpeed() MACROS{ UDCON &= ~(1 << LSM); }MACROE + /* Inline Functions: */ + #if (defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)) + static inline void USB_Device_SetLowSpeed(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetLowSpeed(void) + { + UDCON |= (1 << LSM); + } - #define USB_Device_SetDeviceAddress(addr) MACROS{ UDADDR = ((1 << ADDEN) | (addr & 0x7F)); }MACROE + static inline void USB_Device_SetFullSpeed(void) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetFullSpeed(void) + { + UDCON &= ~(1 << LSM); + } + #endif + static inline void USB_Device_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void USB_Device_SetDeviceAddress(const uint8_t Address) + { + UDADDR = ((1 << ADDEN) | (Address & 0x7F)); + } #endif #endif diff --git a/LUFA/Drivers/USB/LowLevel/Endpoint.h b/LUFA/Drivers/USB/LowLevel/Endpoint.h index 88aae1eee..dd74d5263 100644 --- a/LUFA/Drivers/USB/LowLevel/Endpoint.h +++ b/LUFA/Drivers/USB/LowLevel/Endpoint.h @@ -83,6 +83,7 @@ #include "../../../Common/Common.h" #include "../HighLevel/USBTask.h" + #include "USBInterrupt.h" #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) #include "../HighLevel/StreamCallbacks.h" @@ -149,7 +150,7 @@ /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's * bank size in the device. */ - #define ENDPOINT_EPSIZE_MASK 0x7FF + #define ENDPOINT_EPSIZE_MASK 0x7F /** Maximum size in bytes of a given endpoint. * @@ -176,258 +177,6 @@ #else #define ENDPOINT_TOTAL_ENDPOINTS 1 #endif - - /* Pseudo-Function Macros: */ - #if defined(__DOXYGEN__) - /** Indicates the number of bytes currently stored in the current endpoint's selected bank. - * - * \note The return width of this function may differ, depending on the maximum endpoint bank size - * of the selected AVR model. - * - * \ingroup Group_EndpointRW - * - * \return Total number of bytes in the currently selected Endpoint's FIFO buffer. - */ - static inline uint16_t Endpoint_BytesInEndpoint(void); - - /** Get the endpoint address of the currently selected endpoint. This is typically used to save - * the currently selected endpoint number so that it can be restored after another endpoint has - * been manipulated. - * - * \return Index of the currently selected endpoint. - */ - static inline uint8_t Endpoint_GetCurrentEndpoint(void); - - /** Selects the given endpoint number. If the address from the device descriptors is used, the - * value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint - * number (and discarding the endpoint direction bit). - * - * Any endpoint operations which do not require the endpoint number to be indicated will operate on - * the currently selected endpoint. - * - * \param[in] EndpointNumber Endpoint number to select. - */ - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber); - - /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's - * In and Out pointers to the bank's contents. - * - * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. - */ - static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber); - - /** Enables the currently selected endpoint so that data can be sent and received through it to - * and from a host. - * - * \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint(). - */ - static inline void Endpoint_EnableEndpoint(void); - - /** Disables the currently selected endpoint so that data cannot be sent and received through it - * to and from a host. - */ - static inline void Endpoint_DisableEndpoint(void); - - /** Determines if the currently selected endpoint is enabled, but not necessarily configured. - * - * \return Boolean True if the currently selected endpoint is enabled, false otherwise. - */ - static inline bool Endpoint_IsEnabled(void); - - /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint - * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN - * direction). This function will return false if an error has occurred in the endpoint, if the endpoint - * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN - * direction and the endpoint bank is full. - * - * \ingroup Group_EndpointPacketManagement - * - * \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction. - */ - static inline bool Endpoint_IsReadWriteAllowed(void); - - /** Determines if the currently selected endpoint is configured. - * - * \return Boolean true if the currently selected endpoint has been configured, false otherwise. - */ - static inline bool Endpoint_IsConfigured(void); - - /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their - * interrupt duration has elapsed. Which endpoints have interrupted can be determined by - * masking the return value against (1 << {Endpoint Number}). - * - * \return Mask whose bits indicate which endpoints have interrupted. - */ - static inline uint8_t Endpoint_GetEndpointInterrupts(void); - - /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type - * endpoints). - * - * \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested. - * - * \return Boolean true if the specified endpoint has interrupted, false otherwise. - */ - static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber); - - /** Determines if the selected IN endpoint is ready for a new packet. - * - * \ingroup Group_EndpointPacketManagement - * - * \return Boolean true if the current endpoint is ready for an IN packet, false otherwise. - */ - static inline bool Endpoint_IsINReady(void); - - /** Determines if the selected OUT endpoint has received new packet. - * - * \ingroup Group_EndpointPacketManagement - * - * \return Boolean true if current endpoint is has received an OUT packet, false otherwise. - */ - static inline bool Endpoint_IsOUTReceived(void); - - /** Determines if the current CONTROL type endpoint has received a SETUP packet. - * - * \ingroup Group_EndpointPacketManagement - * - * \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise. - */ - static inline bool Endpoint_IsSETUPReceived(void); - - /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the - * endpoint for the next packet. - * - * \ingroup Group_EndpointPacketManagement - * - * \note This is not applicable for non CONTROL type endpoints. - */ - static inline void Endpoint_ClearSETUP(void); - - /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the - * next packet and switching to the alternative endpoint bank if double banked. - * - * \ingroup Group_EndpointPacketManagement - */ - static inline void Endpoint_ClearIN(void); - - /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint - * for the next packet and switching to the alternative endpoint bank if double banked. - * - * \ingroup Group_EndpointPacketManagement - */ - static inline void Endpoint_ClearOUT(void); - - /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the - * indicated endpoint and that the current transfer sequence should be aborted. This provides a - * way for devices to indicate invalid commands to the host so that the current transfer can be - * aborted and the host can begin its own recovery sequence. - * - * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro - * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected - * endpoint. - * - * \ingroup Group_EndpointPacketManagement - */ - static inline void Endpoint_StallTransaction(void); - - /** Clears the STALL condition on the currently selected endpoint. - * - * \ingroup Group_EndpointPacketManagement - */ - static inline void Endpoint_ClearStall(void); - - /** Determines if the currently selected endpoint is stalled, false otherwise. - * - * \ingroup Group_EndpointPacketManagement - * - * \return Boolean true if the currently selected endpoint is stalled, false otherwise. - */ - static inline bool Endpoint_IsStalled(void); - - /** Resets the data toggle of the currently selected endpoint. */ - static inline void Endpoint_ResetDataToggle(void); - - /** Determines the currently selected endpoint's direction. - * - * \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask. - */ - static inline uint8_t Endpoint_GetEndpointDirection(void); - - /** Sets the direction of the currently selected endpoint. - * - * \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask. - */ - static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask); - #else - #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) - #define Endpoint_BytesInEndpoint() UEBCX - #elif defined(USB_SERIES_4_AVR) - #define Endpoint_BytesInEndpoint() (((uint16_t)UEBCHX << 8) | UEBCLX) - #elif defined(USB_SERIES_2_AVR) - #define Endpoint_BytesInEndpoint() UEBCLX - #endif - - #if !defined(CONTROL_ONLY_DEVICE) - #define Endpoint_GetCurrentEndpoint() (UENUM & ENDPOINT_EPNUM_MASK) - #else - #define Endpoint_GetCurrentEndpoint() ENDPOINT_CONTROLEP - #endif - - #if !defined(CONTROL_ONLY_DEVICE) - #define Endpoint_SelectEndpoint(epnum) MACROS{ UENUM = (epnum); }MACROE - #else - #define Endpoint_SelectEndpoint(epnum) (void)(epnum) - #endif - - #define Endpoint_ResetFIFO(epnum) MACROS{ UERST = (1 << (epnum)); UERST = 0; }MACROE - - #define Endpoint_EnableEndpoint() MACROS{ UECONX |= (1 << EPEN); }MACROE - - #define Endpoint_DisableEndpoint() MACROS{ UECONX &= ~(1 << EPEN); }MACROE - - #define Endpoint_IsEnabled() ((UECONX & (1 << EPEN)) ? true : false) - - #if !defined(CONTROL_ONLY_DEVICE) - #define Endpoint_IsReadWriteAllowed() ((UEINTX & (1 << RWAL)) ? true : false) - #endif - - #define Endpoint_IsConfigured() ((UESTA0X & (1 << CFGOK)) ? true : false) - - #define Endpoint_GetEndpointInterrupts() UEINT - - #define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << (n))) ? true : false) - - #define Endpoint_IsINReady() ((UEINTX & (1 << TXINI)) ? true : false) - - #define Endpoint_IsOUTReceived() ((UEINTX & (1 << RXOUTI)) ? true : false) - - #define Endpoint_IsSETUPReceived() ((UEINTX & (1 << RXSTPI)) ? true : false) - - #define Endpoint_ClearSETUP() MACROS{ UEINTX &= ~(1 << RXSTPI); }MACROE - - #if !defined(CONTROL_ONLY_DEVICE) - #define Endpoint_ClearIN() MACROS{ UEINTX &= ~((1 << TXINI) | (1 << FIFOCON)); }MACROE - #else - #define Endpoint_ClearIN() MACROS{ UEINTX &= ~(1 << TXINI); }MACROE - #endif - - #if !defined(CONTROL_ONLY_DEVICE) - #define Endpoint_ClearOUT() MACROS{ UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON)); }MACROE - #else - #define Endpoint_ClearOUT() MACROS{ UEINTX &= ~(1 << RXOUTI); }MACROE - #endif - - #define Endpoint_StallTransaction() MACROS{ UECONX |= (1 << STALLRQ); }MACROE - - #define Endpoint_ClearStall() MACROS{ UECONX |= (1 << STALLRQC); }MACROE - - #define Endpoint_IsStalled() ((UECONX & (1 << STALLRQ)) ? true : false) - - #define Endpoint_ResetDataToggle() MACROS{ UECONX |= (1 << RSTDT); }MACROE - - #define Endpoint_GetEndpointDirection() (UECFG0X & ENDPOINT_DIR_IN) - - #define Endpoint_SetEndpointDirection(dir) MACROS{ UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | (dir)); }MACROE - #endif /* Enums: */ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function. @@ -497,6 +246,298 @@ }; /* Inline Functions: */ + /** Indicates the number of bytes currently stored in the current endpoint's selected bank. + * + * \note The return width of this function may differ, depending on the maximum endpoint bank size + * of the selected AVR model. + * + * \ingroup Group_EndpointRW + * + * \return Total number of bytes in the currently selected Endpoint's FIFO buffer. + */ + static inline uint16_t Endpoint_BytesInEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint16_t Endpoint_BytesInEndpoint(void) + { + #if defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + return UEBCX; + #elif defined(USB_SERIES_4_AVR) + return (((uint16_t)UEBCHX << 8) | UEBCLX); + #elif defined(USB_SERIES_2_AVR) + return UEBCLX; + #endif + } + + /** Get the endpoint address of the currently selected endpoint. This is typically used to save + * the currently selected endpoint number so that it can be restored after another endpoint has + * been manipulated. + * + * \return Index of the currently selected endpoint. + */ + static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetCurrentEndpoint(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + return (UENUM & ENDPOINT_EPNUM_MASK); + #else + return ENDPOINT_CONTROLEP; + #endif + } + + /** Selects the given endpoint number. If the address from the device descriptors is used, the + * value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint + * number (and discarding the endpoint direction bit). + * + * Any endpoint operations which do not require the endpoint number to be indicated will operate on + * the currently selected endpoint. + * + * \param[in] EndpointNumber Endpoint number to select. + */ + static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) + { + #if !defined(CONTROL_ONLY_DEVICE) + UENUM = EndpointNumber; + #endif + } + + /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's + * In and Out pointers to the bank's contents. + * + * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. + */ + static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetFIFO(const uint8_t EndpointNumber) + { + UERST = (1 << EndpointNumber); + UERST = 0; + } + + /** Enables the currently selected endpoint so that data can be sent and received through it to + * and from a host. + * + * \note Endpoints must first be configured properly via \ref Endpoint_ConfigureEndpoint(). + */ + static inline void Endpoint_EnableEndpoint(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_EnableEndpoint(void) + { + UECONX |= (1 << EPEN); + } + + /** Disables the currently selected endpoint so that data cannot be sent and received through it + * to and from a host. + */ + static inline void Endpoint_DisableEndpoint(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_DisableEndpoint(void) + { + UECONX &= ~(1 << EPEN); + } + + /** Determines if the currently selected endpoint is enabled, but not necessarily configured. + * + * \return Boolean True if the currently selected endpoint is enabled, false otherwise. + */ + static inline bool Endpoint_IsEnabled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsEnabled(void) + { + return ((UECONX & (1 << EPEN)) ? true : false); + } + + /** Determines if the currently selected endpoint may be read from (if data is waiting in the endpoint + * bank and the endpoint is an OUT direction, or if the bank is not yet full if the endpoint is an IN + * direction). This function will return false if an error has occurred in the endpoint, if the endpoint + * is an OUT direction and no packet (or an empty packet) has been received, or if the endpoint is an IN + * direction and the endpoint bank is full. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the currently selected endpoint may be read from or written to, depending on its direction. + */ + static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsReadWriteAllowed(void) + { + return ((UEINTX & (1 << RWAL)) ? true : false); + } + + /** Determines if the currently selected endpoint is configured. + * + * \return Boolean true if the currently selected endpoint has been configured, false otherwise. + */ + static inline bool Endpoint_IsConfigured(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsConfigured(void) + { + return ((UESTA0X & (1 << CFGOK)) ? true : false); + } + + /** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their + * interrupt duration has elapsed. Which endpoints have interrupted can be determined by + * masking the return value against (1 << {Endpoint Number}). + * + * \return Mask whose bits indicate which endpoints have interrupted. + */ + static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetEndpointInterrupts(void) + { + return UEINT; + } + + /** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type + * endpoints). + * + * \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested. + * + * \return Boolean true if the specified endpoint has interrupted, false otherwise. + */ + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) + { + return ((UEINT & (1 << EndpointNumber)) ? true : false); + } + + /** Determines if the selected IN endpoint is ready for a new packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the current endpoint is ready for an IN packet, false otherwise. + */ + static inline bool Endpoint_IsINReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsINReady(void) + { + return ((UEINTX & (1 << TXINI)) ? true : false); + } + + /** Determines if the selected OUT endpoint has received new packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if current endpoint is has received an OUT packet, false otherwise. + */ + static inline bool Endpoint_IsOUTReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsOUTReceived(void) + { + return ((UEINTX & (1 << RXOUTI)) ? true : false); + } + + /** Determines if the current CONTROL type endpoint has received a SETUP packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the selected endpoint has received a SETUP packet, false otherwise. + */ + static inline bool Endpoint_IsSETUPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsSETUPReceived(void) + { + return ((UEINTX & (1 << RXSTPI)) ? true : false); + } + + /** Clears a received SETUP packet on the currently selected CONTROL type endpoint, freeing up the + * endpoint for the next packet. + * + * \ingroup Group_EndpointPacketManagement + * + * \note This is not applicable for non CONTROL type endpoints. + */ + static inline void Endpoint_ClearSETUP(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearSETUP(void) + { + UEINTX &= ~(1 << RXSTPI); + } + + /** Sends an IN packet to the host on the currently selected endpoint, freeing up the endpoint for the + * next packet and switching to the alternative endpoint bank if double banked. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearIN(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearIN(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + UEINTX &= ~((1 << TXINI) | (1 << FIFOCON)); + #else + UEINTX &= ~(1 << TXINI); + #endif + } + + /** Acknowledges an OUT packet to the host on the currently selected endpoint, freeing up the endpoint + * for the next packet and switching to the alternative endpoint bank if double banked. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearOUT(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearOUT(void) + { + #if !defined(CONTROL_ONLY_DEVICE) + UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON)); + #else + UEINTX &= ~(1 << RXOUTI); + #endif + } + + /** Stalls the current endpoint, indicating to the host that a logical problem occurred with the + * indicated endpoint and that the current transfer sequence should be aborted. This provides a + * way for devices to indicate invalid commands to the host so that the current transfer can be + * aborted and the host can begin its own recovery sequence. + * + * The currently selected endpoint remains stalled until either the \ref Endpoint_ClearStall() macro + * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected + * endpoint. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_StallTransaction(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_StallTransaction(void) + { + UECONX |= (1 << STALLRQ); + } + + /** Clears the STALL condition on the currently selected endpoint. + * + * \ingroup Group_EndpointPacketManagement + */ + static inline void Endpoint_ClearStall(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ClearStall(void) + { + UECONX |= (1 << STALLRQC); + } + + /** Determines if the currently selected endpoint is stalled, false otherwise. + * + * \ingroup Group_EndpointPacketManagement + * + * \return Boolean true if the currently selected endpoint is stalled, false otherwise. + */ + static inline bool Endpoint_IsStalled(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_IsStalled(void) + { + return ((UECONX & (1 << STALLRQ)) ? true : false); + } + + /** Resets the data toggle of the currently selected endpoint. */ + static inline void Endpoint_ResetDataToggle(void) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetDataToggle(void) + { + UECONX |= (1 << RSTDT); + } + + /** Determines the currently selected endpoint's direction. + * + * \return The currently selected endpoint's direction, as a ENDPOINT_DIR_* mask. + */ + static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Endpoint_GetEndpointDirection(void) + { + return (UECFG0X & ENDPOINT_DIR_IN); + } + + /** Sets the direction of the currently selected endpoint. + * + * \param[in] DirectionMask New endpoint direction, as a ENDPOINT_DIR_* mask. + */ + static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SetEndpointDirection(const uint8_t DirectionMask) + { + UECFG0X = ((UECFG0X & ~ENDPOINT_DIR_IN) | DirectionMask); + } + /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints. * * \ingroup Group_EndpointPrimitiveRW @@ -936,9 +977,9 @@ * * \ingroup Group_EndpointStreamRW * - * \param[out] Buffer Pointer to the destination data buffer to write to. - * \param[in] Length Number of bytes to send via the currently selected endpoint. - * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * \param[out] Buffer Pointer to the destination data buffer to write to. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. * * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. */ @@ -950,9 +991,9 @@ * * \ingroup Group_EndpointStreamRW * - * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. - * \param[in] Length Number of bytes to send via the currently selected endpoint. - * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. * * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. */ @@ -976,8 +1017,8 @@ * \ingroup Group_EndpointStreamRW * * \param[out] Buffer Pointer to the destination data buffer to write to. - * \param[in] Length Number of bytes to send via the currently selected endpoint. - * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. * * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. */ @@ -989,9 +1030,9 @@ * * \ingroup Group_EndpointStreamRW * - * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. - * \param[in] Length Number of bytes to send via the currently selected endpoint. - * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. + * \param[out] Buffer Pointer to the destination data buffer to write to, located in EEPROM memory space. + * \param[in] Length Number of bytes to send via the currently selected endpoint. + * \param[in] Callback Name of a callback routine to call between successive USB packet transfers, NULL if no callback. * * \return A value from the \ref Endpoint_Stream_RW_ErrorCodes_t enum. */ @@ -1260,13 +1301,6 @@ Endpoint_BytesToEPSizeMask(Size) : \ Endpoint_BytesToEPSizeMaskDynamic(Size)))) - /* Function Prototypes: */ - void Endpoint_ClearEndpoints(void); - uint8_t Endpoint_BytesToEPSizeMaskDynamic(const uint16_t Size); - bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, - const uint8_t UECFG0XData, - const uint8_t UECFG1XData); - /* Inline Functions: */ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE; static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) @@ -1283,6 +1317,12 @@ return (MaskVal << EPSIZE0); } + /* Function Prototypes: */ + void Endpoint_ClearEndpoints(void); + uint8_t Endpoint_BytesToEPSizeMaskDynamic(const uint16_t Size); + bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, + const uint8_t UECFG0XData, + const uint8_t UECFG1XData); #endif /* Disable C linkage for C++ Compilers: */ diff --git a/LUFA/Drivers/USB/LowLevel/Host.h b/LUFA/Drivers/USB/LowLevel/Host.h index d83431b32..3f639c158 100644 --- a/LUFA/Drivers/USB/LowLevel/Host.h +++ b/LUFA/Drivers/USB/LowLevel/Host.h @@ -100,148 +100,6 @@ */ #define HOST_DEVICE_SETTLE_DELAY_MS 1500 #endif - - /* Pseudo-Function Macros: */ - #if defined(__DOXYGEN__) - /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host. - * USB bus resets leave the default control pipe configured (if already configured). - * - * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be - * woken up automatically and the bus resumed after the reset has been correctly issued. - */ - static inline void USB_Host_ResetBus(void); - - /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has - * completed. - * - * \return Boolean true if no bus reset is currently being sent, false otherwise. - */ - static inline void USB_Host_IsBusResetComplete(void); - - /** Resumes USB communications with an attached and enumerated device, by resuming the transmission - * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the - * host and attached device may occur. - */ - static inline void USB_Host_ResumeBus(void); - - /** Suspends the USB bus, preventing any communications from occurring between the host and attached - * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame - * messages to the device. - */ - static inline void USB_Host_SuspendBus(void); - - /** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro, - * false otherwise. While suspended, no USB communications can occur until the bus is resumed, - * except for the Remote Wakeup event from the device if supported. - * - * \return Boolean true if the bus is currently suspended, false otherwise. - */ - static inline bool USB_Host_IsBusSuspended(void); - - /** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or - * false if the attached device is enumerated in Low Speed mode (1.5Mb/s). - * - * \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise. - */ - static inline bool USB_Host_IsDeviceFullSpeed(void); - - /** Determines if the attached device is currently issuing a Remote Wakeup request, requesting - * that the host resume the USB bus and wake up the device, false otherwise. - * - * \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise. - */ - static inline bool USB_Host_IsRemoteWakeupSent(void); - - /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */ - static inline void USB_Host_ClearRemoteWakeupSent(void); - - /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to - * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to - * be resumed. - */ - static inline void USB_Host_ResumeFromWakeupRequest(void); - - /** Determines if a resume from Remote Wakeup request is currently being sent to an attached - * device. - * - * \return Boolean true if no resume request is currently being sent, false otherwise. - */ - static inline bool USB_Host_IsResumeFromWakeupRequestSent(void); - #else - #define USB_Host_ResetBus() MACROS{ UHCON |= (1 << RESET); }MACROE - - #define USB_Host_IsBusResetComplete() ((UHCON & (1 << RESET)) ? false : true) - - #define USB_Host_ResumeBus() MACROS{ UHCON |= (1 << SOFEN); }MACROE - - #define USB_Host_SuspendBus() MACROS{ UHCON &= ~(1 << SOFEN); }MACROE - - #define USB_Host_IsBusSuspended() ((UHCON & (1 << SOFEN)) ? false : true) - - #define USB_Host_IsDeviceFullSpeed() ((USBSTA & (1 << SPEED)) ? true : false) - - #define USB_Host_IsRemoteWakeupSent() ((UHINT & (1 << RXRSMI)) ? true : false) - - #define USB_Host_ClearRemoteWakeupSent() MACROS{ UHINT &= ~(1 << RXRSMI); }MACROE - - #define USB_Host_ResumeFromWakeupRequest() MACROS{ UHCON |= (1 << RESUME); }MACROE - - #define USB_Host_IsResumeFromWakeupRequestSent() ((UHCON & (1 << RESUME)) ? false : true) - #endif - - /* Function Prototypes: */ - /** Convenience function. This routine sends a SetConfiguration standard request to the attached - * device, with the given configuration index. This can be used to easily set the device - * configuration without creating and sending the request manually. - * - * \note After this routine returns, the control pipe will be selected. - * - * \param[in] ConfigNumber Configuration index to send to the device. - * - * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. - */ - uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber); - - /** Convenience function. This routine sends a GetDescriptor standard request to the attached - * device, requesting the device descriptor. This can be used to easily retrieve information - * about the device such as its VID, PID and power requirements. - * - * \note After this routine returns, the control pipe will be selected. - * - * \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where - * the read data is to be stored. - * - * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. - */ - uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr); - - /** Convenience function. This routine sends a GetDescriptor standard request to the attached - * device, requesting the string descriptor of the specified index. This can be used to easily - * retrieve string descriptors from the device by index, after the index is obtained from the - * Device or Configuration descriptors. - * - * \note After this routine returns, the control pipe will be selected. - * - * \param[in] Index Index of the string index to retrieve. - * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is - * to be stored. - * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer. - * - * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. - */ - uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index, - void* const Buffer, - const uint8_t BufferLength); - - /** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device. - * - * \note After this routine returns, the control pipe will be selected. - * - * \param[in] EndpointIndex Index of the endpoint to clear. - * - * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. - */ - uint8_t USB_Host_ClearPipeStall(uint8_t EndpointIndex); /* Enums: */ /** Enum for the various states of the USB Host state machine. Only some states are @@ -385,22 +243,226 @@ */ }; + /* Inline Functions: */ + /** Resets the USB bus, including the endpoints in any attached device and pipes on the AVR host. + * USB bus resets leave the default control pipe configured (if already configured). + * + * If the USB bus has been suspended prior to issuing a bus reset, the attached device will be + * woken up automatically and the bus resumed after the reset has been correctly issued. + */ + static inline void USB_Host_ResetBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResetBus(void) + { + UHCON |= (1 << RESET); + } + + /** Determines if a previously issued bus reset (via the \ref USB_Host_ResetBus() macro) has + * completed. + * + * \return Boolean true if no bus reset is currently being sent, false otherwise. + */ + static inline bool USB_Host_IsBusResetComplete(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsBusResetComplete(void) + { + return ((UHCON & (1 << RESET)) ? false : true); + } + + /** Resumes USB communications with an attached and enumerated device, by resuming the transmission + * of the 1MS Start Of Frame messages to the device. When resumed, USB communications between the + * host and attached device may occur. + */ + static inline void USB_Host_ResumeBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResumeBus(void) + { + UHCON |= (1 << SOFEN); + } + + /** Suspends the USB bus, preventing any communications from occurring between the host and attached + * device until the bus has been resumed. This stops the transmission of the 1MS Start Of Frame + * messages to the device. + */ + static inline void USB_Host_SuspendBus(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_SuspendBus(void) + { + UHCON &= ~(1 << SOFEN); + } + + /** Determines if the USB bus has been suspended via the use of the \ref USB_Host_SuspendBus() macro, + * false otherwise. While suspended, no USB communications can occur until the bus is resumed, + * except for the Remote Wakeup event from the device if supported. + * + * \return Boolean true if the bus is currently suspended, false otherwise. + */ + static inline bool USB_Host_IsBusSuspended(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsBusSuspended(void) + { + return ((UHCON & (1 << SOFEN)) ? false : true); + } + + /** Determines if the attached device is currently enumerated in Full Speed mode (12Mb/s), or + * false if the attached device is enumerated in Low Speed mode (1.5Mb/s). + * + * \return Boolean true if the attached device is enumerated in Full Speed mode, false otherwise. + */ + static inline bool USB_Host_IsDeviceFullSpeed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsDeviceFullSpeed(void) + { + return ((USBSTA & (1 << SPEED)) ? true : false); + } + + /** Determines if the attached device is currently issuing a Remote Wakeup request, requesting + * that the host resume the USB bus and wake up the device, false otherwise. + * + * \return Boolean true if the attached device has sent a Remote Wakeup request, false otherwise. + */ + static inline bool USB_Host_IsRemoteWakeupSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsRemoteWakeupSent(void) + { + return ((UHINT & (1 << RXRSMI)) ? true : false); + } + + /** Clears the flag indicating that a Remote Wakeup request has been issued by an attached device. */ + static inline void USB_Host_ClearRemoteWakeupSent(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ClearRemoteWakeupSent(void) + { + UHINT &= ~(1 << RXRSMI); + } + + /** Accepts a Remote Wakeup request from an attached device. This must be issued in response to + * a device's Remote Wakeup request within 2ms for the request to be accepted and the bus to + * be resumed. + */ + static inline void USB_Host_ResumeFromWakeupRequest(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_ResumeFromWakeupRequest(void) + { + UHCON |= (1 << RESUME); + } + + /** Determines if a resume from Remote Wakeup request is currently being sent to an attached + * device. + * + * \return Boolean true if no resume request is currently being sent, false otherwise. + */ + static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_Host_IsResumeFromWakeupRequestSent(void) + { + return ((UHCON & (1 << RESUME)) ? false : true); + } + + /* Function Prototypes: */ + /** Convenience function. This routine sends a SetConfiguration standard request to the attached + * device, with the given configuration index. This can be used to easily set the device + * configuration without creating and sending the request manually. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] ConfigNumber Configuration index to send to the device. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_SetDeviceConfiguration(const uint8_t ConfigNumber); + + /** Convenience function. This routine sends a GetDescriptor standard request to the attached + * device, requesting the device descriptor. This can be used to easily retrieve information + * about the device such as its VID, PID and power requirements. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[out] DeviceDescriptorPtr Pointer to the destination device descriptor structure where + * the read data is to be stored. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_GetDeviceDescriptor(void* const DeviceDescriptorPtr); + + /** Convenience function. This routine sends a GetDescriptor standard request to the attached + * device, requesting the string descriptor of the specified index. This can be used to easily + * retrieve string descriptors from the device by index, after the index is obtained from the + * Device or Configuration descriptors. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] Index Index of the string index to retrieve. + * \param[out] Buffer Pointer to the destination buffer where the retrieved string descriptor is + * to be stored. + * \param[in] BufferLength Maximum size of the string descriptor which can be stored into the buffer. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_GetDeviceStringDescriptor(const uint8_t Index, + void* const Buffer, + const uint8_t BufferLength); + + /** Clears a stall condition on the given pipe, via a ClearFeature request to the attached device. + * + * \note After this routine returns, the control pipe will be selected. + * + * \param[in] EndpointIndex Index of the endpoint to clear. + * + * \return A value from the \ref USB_Host_SendControlErrorCodes_t enum to indicate the result. + */ + uint8_t USB_Host_ClearPipeStall(uint8_t EndpointIndex); + /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) /* Macros: */ - #define USB_Host_HostMode_On() MACROS{ USBCON |= (1 << HOST); }MACROE - #define USB_Host_HostMode_Off() MACROS{ USBCON &= ~(1 << HOST); }MACROE + static inline void USB_Host_HostMode_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_HostMode_On(void) + { + USBCON |= (1 << HOST); + } + + static inline void USB_Host_HostMode_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_HostMode_Off(void) + { + USBCON &= ~(1 << HOST); + } + + static inline void USB_Host_VBUS_Auto_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_Enable(void) + { + OTGCON &= ~(1 << VBUSHWC); + UHWCON |= (1 << UVCONE); + } + + static inline void USB_Host_VBUS_Manual_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_Enable(void) + { + OTGCON |= (1 << VBUSHWC); + UHWCON &= ~(1 << UVCONE); + + DDRE |= (1 << 7); + } - #define USB_Host_VBUS_Auto_Enable() MACROS{ OTGCON &= ~(1 << VBUSHWC); UHWCON |= (1 << UVCONE); }MACROE - #define USB_Host_VBUS_Manual_Enable() MACROS{ OTGCON |= (1 << VBUSHWC); UHWCON &= ~(1 << UVCONE); DDRE |= (1 << 7); }MACROE + static inline void USB_Host_VBUS_Auto_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_On(void) + { + OTGCON |= (1 << VBUSREQ); + } - #define USB_Host_VBUS_Auto_On() MACROS{ OTGCON |= (1 << VBUSREQ); }MACROE - #define USB_Host_VBUS_Manual_On() MACROS{ PORTE |= (1 << 7); }MACROE + static inline void USB_Host_VBUS_Manual_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_On(void) + { + PORTE |= (1 << 7); + } + + static inline void USB_Host_VBUS_Auto_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Auto_Off(void) + { + OTGCON |= (1 << VBUSRQC); + } - #define USB_Host_VBUS_Auto_Off() MACROS{ OTGCON |= (1 << VBUSRQC); }MACROE - #define USB_Host_VBUS_Manual_Off() MACROS{ PORTE &= ~(1 << 7); }MACROE + static inline void USB_Host_VBUS_Manual_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_Host_VBUS_Manual_Off(void) + { + PORTE &= ~(1 << 7); + } - #define USB_Host_SetDeviceAddress(addr) MACROS{ UHADDR = ((addr) & 0x7F); }MACROE + static inline void USB_Host_SetDeviceAddress(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void USB_Host_SetDeviceAddress(const uint8_t Address) + { + UHADDR = (Address & 0x7F); + } /* Enums: */ enum USB_Host_WaitMSErrorCodes_t diff --git a/LUFA/Drivers/USB/LowLevel/OTG.h b/LUFA/Drivers/USB/LowLevel/OTG.h index 0e323465d..deb786642 100644 --- a/LUFA/Drivers/USB/LowLevel/OTG.h +++ b/LUFA/Drivers/USB/LowLevel/OTG.h @@ -76,66 +76,78 @@ */ #define USB_OTG_STP_DATA 0 - /* Pseudo-Function Macros: */ - #if defined(__DOXYGEN__) - /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device - * that the device wishes to change device/host roles. - */ - static inline void USB_OTG_Device_RequestHNP(void); - - /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other - * connected device. - */ - static inline void USB_OTG_Device_CancelHNPRequest(void); - - /** Determines if the device is currently sending a HNP to an attached host. - * - * \return Boolean true if currently sending a HNP to the other connected device, false otherwise - */ - static inline bool USB_OTG_Device_IsSendingHNP(void); - - /** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB - * interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in - * host mode indicates that VBUS should be applied and a session started. - * - * There are two different methods of sending a SRP - either pulses on the VBUS line, or by - * pulsing the Data + line via the internal pull-up resistor. - * - * \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or - * \ref USB_OTG_STP_DATA. - */ - static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask); - - /** Accepts a HNP from a connected device, indicating that both devices should exchange - * device/host roles. - */ - static inline void USB_OTG_Host_AcceptHNP(void); - - /** Rejects a HNP from a connected device, indicating that both devices should remain in their - * current device/host roles. - */ - static inline void USB_OTG_Host_RejectHNP(void); - - /** Indicates if the connected device is not currently sending a HNP request. - * - * \return Boolean true if a HNP is currently being issued by the connected device, false otherwise. - */ - static inline bool USB_OTG_Host_IsHNPReceived(void); - #else - #define USB_OTG_Device_RequestHNP() MACROS{ OTGCON |= (1 << HNPREQ); }MACROE - - #define USB_OTG_Device_CancelHNPRequest() MACROS{ OTGCON &= ~(1 << HNPREQ); }MACROE - - #define USB_OTG_Device_IsSendingHNP() ((OTGCON & (1 << HNPREQ)) ? true : false) - - #define USB_OTG_Device_InitiateSRP(type) MACROS{ OTGCON = ((OTGCON & ~(1 << SRPSEL)) | ((type) | (1 << SRPREQ))); }MACROE - - #define USB_OTG_Host_AcceptHNP() MACROS{ OTGCON |= (1 << HNPREQ); }MACROE + /* Inline Functions: */ + /** Initiate a Host Negotiation Protocol request. This indicates to the other connected device + * that the device wishes to change device/host roles. + */ + static inline void USB_OTG_Device_RequestHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_RequestHNP(void) + { + OTGCON |= (1 << HNPREQ); + } + + /** Cancel a Host Negotiation Protocol request. This stops a pending HNP request to the other + * connected device. + */ + static inline void USB_OTG_Device_CancelHNPRequest(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_CancelHNPRequest(void) + { + OTGCON &= ~(1 << HNPREQ); + } + + /** Determines if the device is currently sending a HNP to an attached host. + * + * \return Boolean true if currently sending a HNP to the other connected device, false otherwise + */ + static inline bool USB_OTG_Device_IsSendingHNP(void) ATTR_ALWAYS_INLINE; + static inline bool USB_OTG_Device_IsSendingHNP(void) + { + return ((OTGCON & (1 << HNPREQ)) ? true : false); + } + + /** Initiates a Session Request Protocol request. Most OTG devices turn off VBUS when the USB + * interface is not in use, to conserve power. Sending a SRP to a USB OTG device running in + * host mode indicates that VBUS should be applied and a session started. + * + * There are two different methods of sending a SRP - either pulses on the VBUS line, or by + * pulsing the Data + line via the internal pull-up resistor. + * + * \param[in] SRPTypeMask Mask indicating the type of SRP to use, either \ref USB_OTG_SRP_VBUS or + * \ref USB_OTG_STP_DATA. + */ + static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Device_InitiateSRP(const uint8_t SRPTypeMask) + { + OTGCON = ((OTGCON & ~(1 << SRPSEL)) | (SRPTypeMask | (1 << SRPREQ))); + } - #define USB_OTG_Host_RejectHNP() MACROS{ OTGCON &= ~(1 << HNPREQ); }MACROE - - #define USB_OTG_Host_IsHNPReceived() ((OTGCON & (1 << HNPREQ)) ? true : false) - #endif + /** Accepts a HNP from a connected device, indicating that both devices should exchange + * device/host roles. + */ + static inline void USB_OTG_Host_AcceptHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Host_AcceptHNP(void) + { + OTGCON |= (1 << HNPREQ); + } + + /** Rejects a HNP from a connected device, indicating that both devices should remain in their + * current device/host roles. + */ + static inline void USB_OTG_Host_RejectHNP(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTG_Host_RejectHNP(void) + { + OTGCON &= ~(1 << HNPREQ); + } + + /** Indicates if the connected device is not currently sending a HNP request. + * + * \return Boolean true if a HNP is currently being issued by the connected device, false otherwise. + */ + static inline bool USB_OTG_Host_IsHNPReceived(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_OTG_Host_IsHNPReceived(void) + { + return ((OTGCON & (1 << HNPREQ)) ? true : false); + } #endif diff --git a/LUFA/Drivers/USB/LowLevel/Pipe.h b/LUFA/Drivers/USB/LowLevel/Pipe.h index ee43babfe..0b07cbb25 100644 --- a/LUFA/Drivers/USB/LowLevel/Pipe.h +++ b/LUFA/Drivers/USB/LowLevel/Pipe.h @@ -105,6 +105,14 @@ #if !defined(__INCLUDE_FROM_USB_DRIVER) #error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead. #endif + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #if !defined(ENDPOINT_CONTROLEP) && !defined(__DOXYGEN__) + #define ENDPOINT_CONTROLEP 0 + #endif + #endif /* Public Interface - May be used in end-application: */ /* Macros: */ @@ -195,319 +203,6 @@ */ #define PIPE_EPDIR_MASK 0x80 - /* 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. - * - * \pre The currently selected pipe 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 - - #define Pipe_GetErrorFlags() ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT | \ - PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID | \ - PIPE_ERRORFLAG_DATATGL)) | \ - (UPSTAX & PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW)) - - #define Pipe_IsReadWriteAllowed() ((UPINTX & (1 << RWAL)) ? true : false) - - #define Pipe_IsINReceived() ((UPINTX & (1 << RXINI)) ? true : false) - - #define Pipe_IsOUTReady() ((UPINTX & (1 << TXOUTI)) ? true : false) - - #define Pipe_IsSETUPSent() ((UPINTX & (1 << TXSTPI)) ? true : false) - - #define Pipe_ClearIN() MACROS{ UPINTX &= ~((1 << RXINI) | (1 << FIFOCON)); }MACROE - - #define Pipe_ClearOUT() MACROS{ UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON)); }MACROE - - #define Pipe_ClearSETUP() MACROS{ UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON)); }MACROE - - #define Pipe_IsNAKReceived() ((UPINTX & (1 << NAKEDI)) ? true : false) - - #define Pipe_ClearNAKReceived() MACROS{ UPINTX &= ~(1 << NAKEDI); }MACROE - - #define Pipe_IsStalled() ((UPINTX & (1 << RXSTALLI)) ? true : false) - - #define Pipe_ClearStall() MACROS{ UPINTX &= ~(1 << RXSTALLI); }MACROE - #endif - /* Enums: */ /** Enum for the possible error return codes of the Pipe_WaitUntilReady function. * @@ -545,6 +240,386 @@ }; /* 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); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_BoundEndpointNumber(void) + { + return ((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK); + } + + /** 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(const uint8_t Milliseconds) ATTR_ALWAYS_INLINE; + static inline void Pipe_SetInterruptPeriod(const uint8_t Milliseconds) + { + UPCFG2X = 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetPipeInterrupts(void) + { + return UPINT; + } + + /** 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(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) + { + return ((UPINT & (1 << PipeNumber)) ? true : false); + } + + /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */ + static inline void Pipe_Unfreeze(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Unfreeze(void) + { + UPCONX &= ~(1 << PFREEZE); + } + + /** Freezes the selected pipe, preventing it from communicating with an attached device. */ + static inline void Pipe_Freeze(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_Freeze(void) + { + UPCONX |= (1 << PFREEZE); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsFrozen(void) + { + return ((UPCONX & (1 << PFREEZE)) ? true : false); + } + + /** Clears the master pipe error flag. */ + static inline void Pipe_ClearError(void) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearError(void) + { + UPINTX &= ~(1 << PERRI); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsError(void) + { + return ((UPINTX & (1 << PERRI)) ? true : false); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearErrorFlags(void) + { + UPERRX = 0; + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetErrorFlags(void) + { + return ((UPERRX & (PIPE_ERRORFLAG_CRC16 | PIPE_ERRORFLAG_TIMEOUT | + PIPE_ERRORFLAG_PID | PIPE_ERRORFLAG_DATAPID | + PIPE_ERRORFLAG_DATATGL)) | + (UPSTAX & (PIPE_ERRORFLAG_OVERFLOW | PIPE_ERRORFLAG_UNDERFLOW))); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsReadWriteAllowed(void) + { + return ((UPINTX & (1 << RWAL)) ? true : false); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsINReceived(void) + { + return ((UPINTX & (1 << RXINI)) ? true : false); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsOUTReady(void) + { + return ((UPINTX & (1 << TXOUTI)) ? true : false); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsSETUPSent(void) + { + return ((UPINTX & (1 << TXSTPI)) ? true : false); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearSETUP(void) + { + UPINTX &= ~((1 << TXSTPI) | (1 << FIFOCON)); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearIN(void) + { + UPINTX &= ~((1 << RXINI) | (1 << FIFOCON)); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearOUT(void) + { + UPINTX &= ~((1 << TXOUTI) | (1 << FIFOCON)); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsNAKReceived(void) + { + return ((UPINTX & (1 << NAKEDI)) ? true : false); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearNAKReceived(void) + { + UPINTX &= ~(1 << NAKEDI); + } + + /** 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) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_IsStalled(void) + { + return ((UPINTX & (1 << RXSTALLI)) ? true : false); + } + + /** 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) ATTR_ALWAYS_INLINE; + static inline void Pipe_ClearStall(void) + { + UPINTX &= ~(1 << RXSTALLI); + } + /** Reads one byte from the currently selected pipe's bank, for OUT direction pipes. * * \ingroup Group_PipePrimitiveRW @@ -1046,14 +1121,7 @@ __CALLBACK_PARAM) ATTR_NON_NULL_PTR_ARG(1); /* Private Interface - For use in library only: */ - #if !defined(__DOXYGEN__) - /* Macros: */ - #define PIPE_TOKEN_MASK (0x03 << PTOKEN0) - - #if !defined(ENDPOINT_CONTROLEP) - #define ENDPOINT_CONTROLEP 0 - #endif - + #if !defined(__DOXYGEN__) /* Function Prototypes: */ void Pipe_ClearPipes(void); diff --git a/LUFA/Drivers/USB/LowLevel/USBController.h b/LUFA/Drivers/USB/LowLevel/USBController.h index 5542bb02c..f26f77360 100644 --- a/LUFA/Drivers/USB/LowLevel/USBController.h +++ b/LUFA/Drivers/USB/LowLevel/USBController.h @@ -196,20 +196,40 @@ */ #define EP_TYPE_INTERRUPT 0x03 + #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__) + /** Constant for the maximum software timeout period of the USB data stream transfer functions + * (both control and standard) when in either device or host mode. If the next packet of a stream + * is not received or acknowledged within this time period, the stream function will fail. + * + * This value may be overridden in the user project makefile as the value of the + * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch. + */ + #define USB_STREAM_TIMEOUT_MS 100 + #endif + + /* Inline Functions: */ #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) || defined(__DOXYGEN__) /** Returns boolean true if the VBUS line is currently high (i.e. the USB host is supplying power), * otherwise returns false. * - * \note This token is not available on some AVR models which do not support hardware VBUS monitoring. + * \note This function is not available on some AVR models which do not support hardware VBUS monitoring. */ - #define USB_VBUS_GetStatus() ((USBSTA & (1 << VBUS)) ? true : false) + static inline bool USB_VBUS_GetStatus(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_VBUS_GetStatus(void) + { + return ((USBSTA & (1 << VBUS)) ? true : false); + } #endif /** Detaches the device from the USB bus. This has the effect of removing the device from any * attached host, ceasing USB communications. If no host is present, this prevents any host from * enumerating the device once attached until \ref USB_Attach() is called. */ - #define USB_Detach() MACROS{ UDCON |= (1 << DETACH); }MACROE + static inline void USB_Detach(void) ATTR_ALWAYS_INLINE; + static inline void USB_Detach(void) + { + UDCON |= (1 << DETACH); + } /** Attaches the device to the USB bus. This announces the device's presence to any attached * USB host, starting the enumeration process. If no host is present, attaching the device @@ -219,18 +239,11 @@ * attachment of a device to the host. This is despite the bit being located in the device-mode * register and despite the datasheet making no mention of its requirement in host mode. */ - #define USB_Attach() MACROS{ UDCON &= ~(1 << DETACH); }MACROE - - #if !defined(USB_STREAM_TIMEOUT_MS) || defined(__DOXYGEN__) - /** Constant for the maximum software timeout period of the USB data stream transfer functions - * (both control and standard) when in either device or host mode. If the next packet of a stream - * is not received or acknowledged within this time period, the stream function will fail. - * - * This value may be overridden in the user project makefile as the value of the - * \ref USB_STREAM_TIMEOUT_MS token, and passed to the compiler using the -D switch. - */ - #define USB_STREAM_TIMEOUT_MS 100 - #endif + static inline void USB_Attach(void) ATTR_ALWAYS_INLINE; + static inline void USB_Attach(void) + { + UDCON &= ~(1 << DETACH); + } /* Function Prototypes: */ /** Main function to initialize and start the USB interface. Once active, the USB interface will @@ -342,31 +355,93 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) - /* Macros: */ - #define USB_PLL_On() MACROS{ PLLCSR = USB_PLL_PSC; PLLCSR |= (1 << PLLE); }MACROE - #define USB_PLL_Off() MACROS{ PLLCSR = 0; }MACROE - #define USB_PLL_IsReady() ((PLLCSR & (1 << PLOCK)) ? true : false) + /* Inline Functions: */ + static inline void USB_PLL_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_PLL_On(void) + { + PLLCSR = USB_PLL_PSC; + PLLCSR |= (1 << PLLE); + } + + static inline void USB_PLL_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_PLL_Off(void) + { + PLLCSR = 0; + } + + static inline bool USB_PLL_IsReady(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool USB_PLL_IsReady(void) + { + return ((PLLCSR & (1 << PLOCK)) ? true : false); + } + + static inline void USB_REG_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_REG_On(void) + { + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + UHWCON |= (1 << UVREGE); + #else + REGCR &= ~(1 << REGDIS); + #endif + } + static inline void USB_REG_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_REG_Off(void) + { #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) - #define USB_REG_On() MACROS{ UHWCON |= (1 << UVREGE); }MACROE - #define USB_REG_Off() MACROS{ UHWCON &= ~(1 << UVREGE); }MACROE + UHWCON &= ~(1 << UVREGE); #else - #define USB_REG_On() MACROS{ REGCR &= ~(1 << REGDIS); }MACROE - #define USB_REG_Off() MACROS{ REGCR |= (1 << REGDIS); }MACROE + REGCR |= (1 << REGDIS); + #endif + } + + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + static inline void USB_OTGPAD_On(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTGPAD_On(void) + { + USBCON |= (1 << OTGPADE); + } + + static inline void USB_OTGPAD_Off(void) ATTR_ALWAYS_INLINE; + static inline void USB_OTGPAD_Off(void) + { + USBCON &= ~(1 << OTGPADE); + } #endif + + static inline void USB_CLK_Freeze(void) ATTR_ALWAYS_INLINE; + static inline void USB_CLK_Freeze(void) + { + USBCON |= (1 << FRZCLK); + } + + static inline void USB_CLK_Unfreeze(void) ATTR_ALWAYS_INLINE; + static inline void USB_CLK_Unfreeze(void) + { + USBCON &= ~(1 << FRZCLK); + } - #define USB_OTGPAD_On() MACROS{ USBCON |= (1 << OTGPADE); }MACROE - #define USB_OTGPAD_Off() MACROS{ USBCON &= ~(1 << OTGPADE); }MACROE + static inline void USB_Controller_Enable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Enable(void) + { + USBCON |= (1 << USBE); + } - #define USB_CLK_Freeze() MACROS{ USBCON |= (1 << FRZCLK); }MACROE - #define USB_CLK_Unfreeze() MACROS{ USBCON &= ~(1 << FRZCLK); }MACROE + static inline void USB_Controller_Disable(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Disable(void) + { + USBCON &= ~(1 << USBE); + } - #define USB_Controller_Enable() MACROS{ USBCON |= (1 << USBE); }MACROE - #define USB_Controller_Disable() MACROS{ USBCON &= ~(1 << USBE); }MACROE - #define USB_Controller_Reset() MACROS{ const uint8_t Temp = USBCON; USBCON = (Temp & ~(1 << USBE)); \ - USBCON = (Temp | (1 << USBE)); }MACROE + static inline void USB_Controller_Reset(void) ATTR_ALWAYS_INLINE; + static inline void USB_Controller_Reset(void) + { + const uint8_t Temp = USBCON; + + USBCON = (Temp & ~(1 << USBE)); + USBCON = (Temp | (1 << USBE)); + } - /* Inline Functions: */ #if defined(USB_CAN_BE_BOTH) static inline uint8_t USB_GetUSBModeFromUID(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; static inline uint8_t USB_GetUSBModeFromUID(void) diff --git a/LUFA/Drivers/USB/LowLevel/USBInterrupt.h b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h index f954468be..6e62beccf 100644 --- a/LUFA/Drivers/USB/LowLevel/USBInterrupt.h +++ b/LUFA/Drivers/USB/LowLevel/USBInterrupt.h @@ -47,11 +47,6 @@ #include <util/atomic.h> #include <stdbool.h> - #include "../../../Common/Common.h" - #include "../HighLevel/USBMode.h" - #include "../HighLevel/Events.h" - #include "USBController.h" - /* Enable C linkage for C++ Compilers: */ #if defined(__cplusplus) extern "C" { @@ -90,6 +85,12 @@ #define USB_INT_RSTI UHIEN , (1 << RSTE) , UHINT , (1 << RSTI) #define USB_INT_SRPI OTGIEN, (1 << SRPE) , OTGINT, (1 << SRPI) #define USB_INT_RXSTPI UEIENX, (1 << RXSTPE) , UEINTX, (1 << RXSTPI) + + /* Includes: */ + #include "../../../Common/Common.h" + #include "../HighLevel/USBMode.h" + #include "../HighLevel/Events.h" + #include "USBController.h" /* Function Prototypes: */ void USB_INT_ClearAllInterrupts(void); |