diff options
author | Dean Camera <dean@fourwalledcubicle.com> | 2012-05-10 19:24:58 +0000 |
---|---|---|
committer | Dean Camera <dean@fourwalledcubicle.com> | 2012-05-10 19:24:58 +0000 |
commit | 359fbfe14d00ab378f85a36664820ea9ba538c3f (patch) | |
tree | 0929d5663a3be4dc078dda0aba5ba798ebb627ab /LUFA/Drivers/USB/Core | |
parent | e8570c4a37e41117e3fd1e989e0b41f1e9608f3c (diff) | |
download | lufa-359fbfe14d00ab378f85a36664820ea9ba538c3f.tar.gz lufa-359fbfe14d00ab378f85a36664820ea9ba538c3f.tar.bz2 lufa-359fbfe14d00ab378f85a36664820ea9ba538c3f.zip |
Add branch for the conversion of demos to use standard C header files for configuration, rather than makefile defined macros.
Diffstat (limited to 'LUFA/Drivers/USB/Core')
26 files changed, 509 insertions, 573 deletions
diff --git a/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c b/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c index bcf904d99..4440b7631 100644 --- a/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c +++ b/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c @@ -42,6 +42,21 @@ uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE; #endif +bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries) +{ + for (uint8_t i = 0; i < Entries; i++) + { + if (!(Table[i].Address)) + continue; + + if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks))) + return false; + } + + return true; +} + bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, const uint8_t UECFG0XData, const uint8_t UECFG1XData) diff --git a/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h b/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h index 10f69a8fd..37ff220e3 100644 --- a/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h +++ b/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h @@ -89,35 +89,6 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) - /* Macros: */ - #define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails) - #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize) - - #define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails) - #define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks) - - #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) - #define ENDPOINT_DETAILS_MAXEP 7 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 256, 2 - #define ENDPOINT_DETAILS_EP2 64, 2 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #define ENDPOINT_DETAILS_EP5 64, 2 - #define ENDPOINT_DETAILS_EP6 64, 2 - #else - #define ENDPOINT_DETAILS_MAXEP 5 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 64, 1 - #define ENDPOINT_DETAILS_EP2 64, 1 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #endif - /* Inline Functions: */ static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST ATTR_ALWAYS_INLINE; @@ -145,23 +116,6 @@ /* Public Interface - May be used in end-application: */ /* Macros: */ - /** \name Endpoint Bank Mode Masks */ - //@{ - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have one single bank, which requires less USB FIFO memory but results - * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's - * bank at the one time. - */ - #define ENDPOINT_BANK_SINGLE (0 << EPBK0) - - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have two banks, which requires more USB FIFO memory but results - * in faster transfers as one USB device (the AVR or the host) can access one bank while the other - * accesses the second bank. - */ - #define ENDPOINT_BANK_DOUBLE (1 << EPBK0) - //@} - #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined. @@ -169,30 +123,16 @@ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8 #endif - /** Retrieves the maximum bank size in bytes of a given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex) - - /** Retrieves the total number of banks supported by the given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex) - #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__) - /** Total number of endpoints (including the default control endpoint at address 0) which may - * be used in the device. Different USB AVR models support different amounts of endpoints, - * this value reflects the maximum number of endpoints for the currently selected AVR model. - */ - #define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP + #if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR) + #define ENDPOINT_TOTAL_ENDPOINTS 7 + #else + /** Total number of endpoints (including the default control endpoint at address 0) which may + * be used in the device. Different USB AVR models support different amounts of endpoints, + * this value reflects the maximum number of endpoints for the currently selected AVR model. + */ + #define ENDPOINT_TOTAL_ENDPOINTS 5 + #endif #else #define ENDPOINT_TOTAL_ENDPOINTS 1 #endif @@ -222,28 +162,20 @@ }; /* Inline Functions: */ - /** Configures the specified endpoint number with the given endpoint type, direction, bank size - * and banking mode. Once configured, the endpoint may be read from or written to, depending - * on its direction. + /** Configures the specified endpoint address with the given endpoint type, bank size and number of hardware + * banks. Once configured, the endpoint may be read from or written to, depending on its direction. * - * \param[in] Number Endpoint number to configure. This must be more than 0 and less than - * \ref ENDPOINT_TOTAL_ENDPOINTS. + * \param[in] Address Endpoint address to configure. * * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types * are available on Low Speed USB devices - refer to the USB 2.0 specification. * - * \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN. - * All endpoints (except Control type) are unidirectional - data may only be read - * from or written to the endpoint bank based on its direction, not both. - * * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted * to the USB host, or after they have been received from the USB host (depending on * the endpoint's data direction). The bank size must indicate the maximum packet size * that the endpoint can handle. * - * \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask. - * More banks uses more USB DPRAM, but offers better performance. Isochronous type - * endpoints <b>must</b> have at least two banks. + * \param[in] Banks Number of banks to use for the endpoint being configured. * * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in * ascending order, or bank corruption will occur. @@ -261,19 +193,18 @@ * * \return Boolean \c true if the configuration succeeded, \c false otherwise. */ - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) ATTR_ALWAYS_INLINE; - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) { - return Endpoint_ConfigureEndpoint_Prv(Number, ((Type << EPTYPE0) | (Direction ? (1 << EPDIR) : 0)), - ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size))); + return Endpoint_ConfigureEndpoint_Prv((Address & ENDPOINT_EPNUM_MASK), + ((Type << EPTYPE0) | ((Address & ENDPOINT_DIR_IN) ? (1 << EPDIR) : 0)), + ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Endpoint_BytesToEPSizeMask(Size))); } /** Indicates the number of bytes currently stored in the current endpoint's selected bank. @@ -294,9 +225,19 @@ #endif } + /** Determines the currently selected endpoint's direction. + * + * \return The currently selected endpoint's direction, as a \c 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 & (1 << EPDIR)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT; + } + /** 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. + * the currently selected endpoint so that it can be restored after another endpoint has been + * manipulated. * * \return Index of the currently selected endpoint. */ @@ -304,38 +245,36 @@ static inline uint8_t Endpoint_GetCurrentEndpoint(void) { #if !defined(CONTROL_ONLY_DEVICE) - return (UENUM & ENDPOINT_EPNUM_MASK); + return ((UENUM & ENDPOINT_EPNUM_MASK) | Endpoint_GetEndpointDirection()); #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). + /** Selects the given endpoint address. * - * Any endpoint operations which do not require the endpoint number to be indicated will operate on + * Any endpoint operations which do not require the endpoint address to be indicated will operate on * the currently selected endpoint. * - * \param[in] EndpointNumber Endpoint number to select. + * \param[in] Address Endpoint address to select. */ - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SelectEndpoint(const uint8_t Address) { #if !defined(CONTROL_ONLY_DEVICE) - UENUM = EndpointNumber; + UENUM = (Address & ENDPOINT_EPNUM_MASK); #endif } /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's * data In and Out pointers to the bank's contents. * - * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. + * \param[in] Address Endpoint address whose FIFO buffers are to be reset. */ - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetEndpoint(const uint8_t Address) { - UERST = (1 << EndpointNumber); + UERST = (1 << (Address & ENDPOINT_EPNUM_MASK)); UERST = 0; } @@ -441,14 +380,14 @@ /** 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. + * \param[in] Address Address of the endpoint whose interrupt flag should be tested. * * \return Boolean \c true if the specified endpoint has interrupted, \c 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) + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) { - return ((Endpoint_GetEndpointInterrupts() & (1 << EndpointNumber)) ? true : false); + return ((Endpoint_GetEndpointInterrupts() & (1 << (Address & ENDPOINT_EPNUM_MASK))) ? true : false); } /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host. @@ -576,16 +515,6 @@ UECONX |= (1 << RSTDT); } - /** Determines the currently selected endpoint's direction. - * - * \return The currently selected endpoint's direction, as a \c 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 & (1 << EPDIR)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT; - } - /** Sets the direction of the currently selected endpoint. * * \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask. @@ -841,6 +770,20 @@ #endif /* Function Prototypes: */ + /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple + * endpoints at the same time. + * + * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the + * control endpoint. + * + * \param[in] Table Pointer to a table of endpoint descriptions. + * \param[in] Entries Number of entries in the endpoint table to configure. + * + * \return Boolean \c true if all endpoints configured successfully, \c false otherwise. + */ + bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries); + /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically, * with respect to the data direction. This is a convenience function which can be used to * simplify user control request handling. diff --git a/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c b/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c index 3f27c7631..a1e0fd371 100644 --- a/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c +++ b/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c @@ -114,9 +114,7 @@ void USB_Host_ProcessNextHostState(void) HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe); break; case HOST_STATE_Powered_ConfigPipe: - if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, - PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, - PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE))) + if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1))) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; @@ -151,9 +149,7 @@ void USB_Host_ProcessNextHostState(void) HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset); break; case HOST_STATE_Default_PostReset: - if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, - PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, - USB_Host_ControlPipeSize, PIPE_BANK_SINGLE))) + if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1))) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; diff --git a/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c b/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c index 5e68cc725..1ddffb51e 100644 --- a/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c +++ b/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c @@ -40,21 +40,43 @@ uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE; -bool Pipe_ConfigurePipe(const uint8_t Number, +bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table, + const uint8_t Entries) +{ + for (uint8_t i = 0; i < Entries; i++) + { + if (!(Table[i].Address)) + continue; + + if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks))) + { + return false; + } + } + + return true; +} + +bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, - const uint8_t Token, - const uint8_t EndpointNumber, + const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks) { + uint8_t Number = (Address & PIPE_EPNUM_MASK); + uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT; + + if (Type == EP_TYPE_CONTROL) + Token = PIPE_TOKEN_SETUP; + #if defined(ORDERED_EP_CONFIG) Pipe_SelectPipe(Number); Pipe_EnablePipe(); UPCFG1X = 0; - UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0)); - UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size)); + UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0)); + UPCFG1X = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size)); Pipe_SetInfiniteINRequests(); @@ -71,7 +93,7 @@ bool Pipe_ConfigurePipe(const uint8_t Number, if (PNum == Number) { - UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0)); + UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0)); UPCFG1XTemp = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size)); UPCFG2XTemp = 0; UPIENXTemp = 0; diff --git a/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h b/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h index 86792bf22..1012fa060 100644 --- a/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h +++ b/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h @@ -124,38 +124,22 @@ /** \name Pipe Token Masks */ //@{ - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes), * which will trigger a control request on the attached device when data is written to the pipe. */ #define PIPE_TOKEN_SETUP (0 << PTOKEN0) - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes), * indicating that the pipe data will flow from device to host. */ #define PIPE_TOKEN_IN (1 << PTOKEN0) - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes), * indicating that the pipe data will flow from host to device. */ #define PIPE_TOKEN_OUT (2 << PTOKEN0) //@} - /** \name Pipe Bank Mode Masks */ - //@{ - /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe - * should have one single bank, which requires less USB FIFO memory but results in slower transfers as - * only one USB device (the AVR or the attached device) can access the pipe's bank at the one time. - */ - #define PIPE_BANK_SINGLE (0 << EPBK0) - - /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe - * should have two banks, which requires more USB FIFO memory but results in faster transfers as one - * USB device (the AVR or the attached device) can access one bank while the other accesses the second - * bank. - */ - #define PIPE_BANK_DOUBLE (1 << EPBK0) - //@} - /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value * in the device descriptor of the attached device. */ @@ -203,36 +187,46 @@ return UPBCX; } + /** Determines the currently selected pipe's direction. + * + * \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask. + */ + static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetPipeDirection(void) + { + return (UPCFG0X & (1 << EPDIR)) ? PIPE_DIR_IN : PIPE_DIR_OUT; + } + /** 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. + * currently selected pipe address 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); + return ((UPNUM & PIPE_PIPENUM_MASK) | Pipe_GetPipeDirection()); } - /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be + /** Selects the given pipe address. Any pipe operations which do not require the pipe address to be * indicated will operate on the currently selected pipe. * - * \param[in] PipeNumber Index of the pipe to select. + * \param[in] Address Address 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) + static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Pipe_SelectPipe(const uint8_t Address) { - UPNUM = PipeNumber; + UPNUM = (Address & PIPE_PIPENUM_MASK); } /** Resets the desired pipe, including the pipe banks and flags. * - * \param[in] PipeNumber Index of the pipe to reset. + * \param[in] Address Address 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) + static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Pipe_ResetPipe(const uint8_t Address) { - UPRST = (1 << PipeNumber); + UPRST = (1 << (Address & PIPE_PIPENUM_MASK)); UPRST = 0; } @@ -326,8 +320,9 @@ static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; static inline uint8_t Pipe_GetBoundEndpointAddress(void) { - return (((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK) | - ((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_EPDIR_MASK : 0)); + uint8_t UPCFG0X_Temp = UPCFG0X; + + return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) | ((UPCFG0X_Temp & PEPNUM1) ? ENDPOINT_DIR_OUT : ENDPOINT_DIR_IN)); } /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds. @@ -351,17 +346,17 @@ return UPINT; } - /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type + /** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type * pipes). * - * \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested. + * \param[in] Address Address of the pipe whose interrupt flag should be tested. * * \return Boolean \c true if the specified pipe has interrupted, \c 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) + static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) { - return ((UPINT & (1 << PipeNumber)) ? true : false); + return ((UPINT & (1 << (Address & PIPE_PIPENUM_MASK))) ? true : false); } /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */ @@ -810,8 +805,22 @@ extern uint8_t USB_Host_ControlPipeSize; /* Function Prototypes: */ - /** Configures the specified pipe number with the given pipe type, token, target endpoint number in the - * attached device, bank size and banking mode. + /** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple + * pipes at the same time. + * + * \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the + * control pipe. + * + * \param[in] Table Pointer to a table of pipe descriptions. + * \param[in] Entries Number of entries in the pipe table to configure. + * + * \return Boolean \c true if all pipes configured successfully, \c false otherwise. + */ + bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table, + const uint8_t Entries); + + /** Configures the specified pipe address with the given pipe type, endpoint address within the attached device, bank size + * and number of hardware banks. * * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze() * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or @@ -819,25 +828,19 @@ * numbers of IN requests without automatic freezing - this can be overridden by a call to * \ref Pipe_SetFiniteINRequests(). * - * \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES. - * - * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low - * Speed USB devices - refer to the USB 2.0 specification. + * \param[in] Address Pipe address to configure. * - * \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN. - * All pipes (except Control type) are unidirectional - data may only be read from or - * written to the pipe bank based on its direction, not both. + * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low + * Speed USB devices - refer to the USB 2.0 specification. * - * \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to. + * \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to. * - * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to - * the USB device, or after they have been received from the USB device (depending on - * the pipe's data direction). The bank size must indicate the maximum packet size that - * the pipe can handle. + * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to + * the USB device, or after they have been received from the USB device (depending on + * the pipe's data direction). The bank size must indicate the maximum packet size that + * the pipe can handle. * - * \param[in] Banks Number of banks to use for the pipe being configured, a \c PIPE_BANK_* mask. More banks - * uses more USB DPRAM, but offers better performance. Isochronous type pipes <b>must</b> - * have at least two banks. + * \param[in] Banks Number of banks to use for the pipe being configured. * * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order, * or bank corruption will occur. @@ -855,10 +858,9 @@ * * \return Boolean \c true if the configuration succeeded, \c false otherwise. */ - bool Pipe_ConfigurePipe(const uint8_t Number, + bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, - const uint8_t Token, - const uint8_t EndpointNumber, + const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks); diff --git a/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c b/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c index e31b88d5f..1f37dfd49 100644 --- a/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c +++ b/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c @@ -232,8 +232,7 @@ static void USB_Init_Device(void) #endif Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); USB_INT_Clear(USB_INT_SUSPI); USB_INT_Enable(USB_INT_SUSPI); diff --git a/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c b/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c index f63cf3eb9..e26c86f12 100644 --- a/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c +++ b/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c @@ -171,8 +171,7 @@ ISR(USB_GEN_vect, ISR_BLOCK) USB_INT_Enable(USB_INT_WAKEUPI); Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); #if defined(INTERRUPT_CONTROL_ENDPOINT) USB_INT_Enable(USB_INT_RXSTPI); diff --git a/LUFA/Drivers/USB/Core/DeviceStandardReq.c b/LUFA/Drivers/USB/Core/DeviceStandardReq.c index 61082cfbb..f5e1cca33 100644 --- a/LUFA/Drivers/USB/Core/DeviceStandardReq.c +++ b/LUFA/Drivers/USB/Core/DeviceStandardReq.c @@ -289,7 +289,6 @@ static void USB_Device_GetStatus(void) switch (USB_ControlRequest.bmRequestType) { - #if !defined(NO_DEVICE_SELF_POWER) || !defined(NO_DEVICE_REMOTE_WAKEUP) case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE): #if !defined(NO_DEVICE_SELF_POWER) if (USB_Device_CurrentlySelfPowered) @@ -301,17 +300,16 @@ static void USB_Device_GetStatus(void) CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED; #endif break; - #endif - #if !defined(CONTROL_ONLY_DEVICE) case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT): + #if !defined(CONTROL_ONLY_DEVICE) Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK); CurrentStatus = Endpoint_IsStalled(); Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP); + #endif break; - #endif default: return; } diff --git a/LUFA/Drivers/USB/Core/Endpoint.h b/LUFA/Drivers/USB/Core/Endpoint.h index 1fcc6b6f3..b349adfc9 100644 --- a/LUFA/Drivers/USB/Core/Endpoint.h +++ b/LUFA/Drivers/USB/Core/Endpoint.h @@ -87,6 +87,18 @@ #endif /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** Type define for a endpoint table entry, used to configure endpoints in groups via + * \ref Endpoint_ConfigureEndpointTable(). + */ + typedef struct + { + uint8_t Address; /**< Address of the endpoint to configure, or zero if the table entry is to be unused. */ + uint16_t Size; /**< Size of the endpoint bank, in bytes. */ + uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */ + uint8_t Banks; /**< Number of hardware banks to use for the endpoint. */ + } USB_Endpoint_Table_t; + /* Macros: */ /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's * numerical address in the device. diff --git a/LUFA/Drivers/USB/Core/Pipe.h b/LUFA/Drivers/USB/Core/Pipe.h index bb56b8102..faa803b6d 100644 --- a/LUFA/Drivers/USB/Core/Pipe.h +++ b/LUFA/Drivers/USB/Core/Pipe.h @@ -97,6 +97,19 @@ #endif /* Public Interface - May be used in end-application: */ + /* Type Defines: */ + /** Type define for a pipe table entry, used to configure pipes in groups via + * \ref Pipe_ConfigurePipeTable(). + */ + typedef struct + { + uint8_t Address; /**< Address of the pipe to configure, or zero if the table entry is to be unused. */ + uint16_t Size; /**< Size of the pipe bank, in bytes. */ + uint8_t EndpointAddress; /** Address of the endpoint in the connected device. */ + uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */ + uint8_t Banks; /**< Number of hardware banks to use for the pipe. */ + } USB_Pipe_Table_t; + /* Macros: */ /** Pipe address for the default control pipe, which always resides in address 0. This is * defined for convenience to give more readable code when used with the pipe macros. @@ -113,11 +126,6 @@ */ #define PIPE_EPNUM_MASK 0x0F - /** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's - * direction for comparing with the \c ENDPOINT_DIR_* masks. - */ - #define PIPE_EPDIR_MASK 0x80 - /* Architecture Includes: */ #if (ARCH == ARCH_AVR8) #include "AVR8/Pipe_AVR8.h" diff --git a/LUFA/Drivers/USB/Core/StdDescriptors.h b/LUFA/Drivers/USB/Core/StdDescriptors.h index cee2d5ec0..c46129c48 100644 --- a/LUFA/Drivers/USB/Core/StdDescriptors.h +++ b/LUFA/Drivers/USB/Core/StdDescriptors.h @@ -94,8 +94,8 @@ * * \param[in] x Version number to encode as a 16-bit little-endian number, as a floating point number. */ - #define VERSION_BCD(x) CPU_TO_LE16((((VERSION_TENS(x) << 4) | VERSION_ONES(x)) << 8) | \ - ((VERSION_TENTHS(x) << 4) | VERSION_HUNDREDTHS(x))) + #define VERSION_BCD(x) CPU_TO_LE16((VERSION_TENS(x) << 12) | (VERSION_ONES(x) << 8) | \ + (VERSION_TENTHS(x) << 4) | (VERSION_HUNDREDTHS(x) << 0) ) /** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors * to indicate that the English language is supported by the device in its string descriptors. @@ -722,10 +722,10 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) /* Macros: */ - #define VERSION_TENS(x) (int)((x) / 10) - #define VERSION_ONES(x) (int)((x) - (10 * VERSION_TENS(x))) - #define VERSION_TENTHS(x) (int)(((x) - (int)(x)) * 10) - #define VERSION_HUNDREDTHS(x) (int)((((x) - (int)(x)) * 100) - (10 * VERSION_TENTHS(x))) + #define VERSION_TENS(x) (int)((int)(x) / 10) + #define VERSION_ONES(x) (int)((int)(x) % 10) + #define VERSION_TENTHS(x) (int)(((x * 1) - ((int)(x * 1))) * 10) + #define VERSION_HUNDREDTHS(x) (int)(((x * 10) - ((int)(x * 10))) * 10) #endif /* Disable C linkage for C++ Compilers: */ diff --git a/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c b/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c index fc1b18a2e..c027585a6 100644 --- a/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c +++ b/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c @@ -45,6 +45,23 @@ uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE; volatile uint32_t USB_Endpoint_SelectedEndpoint = ENDPOINT_CONTROLEP; volatile uint8_t* USB_Endpoint_FIFOPos[ENDPOINT_TOTAL_ENDPOINTS]; +bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries) +{ + for (uint8_t i = 0; i < Entries; i++) + { + if (!(Table[i].Address)) + continue; + + if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks))) + { + return false; + } + } + + return true; +} + bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number, const uint32_t UECFG0Data) { diff --git a/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h b/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h index c919effa7..84801a13f 100644 --- a/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h +++ b/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h @@ -90,47 +90,6 @@ /* Private Interface - For use in library only: */ #if !defined(__DOXYGEN__) /* Macros: */ - #define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails) - #define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize) - - #define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex) - #define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails) - #define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks) - - #if defined(USB_SERIES_UC3A0_AVR32) || defined(USB_SERIES_UC3A1_AVR32) - #define ENDPOINT_DETAILS_MAXEP 7 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 256, 2 - #define ENDPOINT_DETAILS_EP2 256, 2 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #define ENDPOINT_DETAILS_EP5 256, 2 - #define ENDPOINT_DETAILS_EP6 256, 2 - #elif defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) - #define ENDPOINT_DETAILS_MAXEP 8 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 512, 3 - #define ENDPOINT_DETAILS_EP2 512, 3 - #define ENDPOINT_DETAILS_EP3 512, 3 - #define ENDPOINT_DETAILS_EP4 512, 3 - #define ENDPOINT_DETAILS_EP5 512, 3 - #define ENDPOINT_DETAILS_EP6 512, 3 - #define ENDPOINT_DETAILS_EP7 512, 3 - #elif defined(USB_SERIES_UC3B0_AVR32) || defined(USB_SERIES_UC3B1_AVR32) - #define ENDPOINT_DETAILS_MAXEP 7 - - #define ENDPOINT_DETAILS_EP0 64, 1 - #define ENDPOINT_DETAILS_EP1 64, 2 - #define ENDPOINT_DETAILS_EP2 64, 2 - #define ENDPOINT_DETAILS_EP3 64, 2 - #define ENDPOINT_DETAILS_EP4 64, 2 - #define ENDPOINT_DETAILS_EP5 256, 2 - #define ENDPOINT_DETAILS_EP6 256, 2 - #endif - #define ENDPOINT_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL) /* Inline Functions: */ @@ -162,34 +121,6 @@ /* Public Interface - May be used in end-application: */ /* Macros: */ - /** \name Endpoint Bank Mode Masks */ - //@{ - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have one single bank, which requires less USB FIFO memory but results - * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's - * bank at the one time. - */ - #define ENDPOINT_BANK_SINGLE AVR32_USBB_UECFG0_EPBK_SINGLE - - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have two banks, which requires more USB FIFO memory but results - * in faster transfers as one USB device (the AVR or the host) can access one bank while the other - * accesses the second bank. - */ - #define ENDPOINT_BANK_DOUBLE AVR32_USBB_UECFG0_EPBK_DOUBLE - - #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__) - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have three banks, which requires more USB FIFO memory but results - * in faster transfers as one USB device (the AVR or the host) can access one bank while the other - * accesses the remaining banks. - * - * \note Not available on all AVR models. - */ - #define ENDPOINT_BANK_TRIPLE AVR32_USBB_UECFG0_EPBK_TRIPLE - #endif - //@} - #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined. @@ -197,30 +128,16 @@ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8 #endif - /** Retrieves the maximum bank size in bytes of a given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex) - - /** Retrieves the total number of banks supported by the given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex) - #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__) - /** Total number of endpoints (including the default control endpoint at address 0) which may - * be used in the device. Different AVR models support different amounts of endpoints, - * this value reflects the maximum number of endpoints for the currently selected AVR model. - */ - #define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP + #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) + #define ENDPOINT_TOTAL_ENDPOINTS 8 + #else + /** Total number of endpoints (including the default control endpoint at address 0) which may + * be used in the device. Different AVR models support different amounts of endpoints, + * this value reflects the maximum number of endpoints for the currently selected AVR model. + */ + #define ENDPOINT_TOTAL_ENDPOINTS 7 + #endif #else #define ENDPOINT_TOTAL_ENDPOINTS 1 #endif @@ -250,28 +167,21 @@ }; /* Inline Functions: */ - /** Configures the specified endpoint number with the given endpoint type, direction, bank size + /** Configures the specified endpoint address with the given endpoint type, direction, bank size * and banking mode. Once configured, the endpoint may be read from or written to, depending * on its direction. * - * \param[in] Number Endpoint number to configure. This must be more than 0 and less than - * \ref ENDPOINT_TOTAL_ENDPOINTS. + * \param[in] Address Endpoint address to configure. * * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types * are available on Low Speed USB devices - refer to the USB 2.0 specification. * - * \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN. - * All endpoints (except Control type) are unidirectional - data may only be read - * from or written to the endpoint bank based on its direction, not both. - * * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted * to the USB host, or after they have been received from the USB host (depending on * the endpoint's data direction). The bank size must indicate the maximum packet size * that the endpoint can handle. * - * \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask. - * More banks uses more USB DPRAM, but offers better performance. Isochronous type - * endpoints <b>must</b> have at least two banks. + * \param[in] Banks Number of hardware banks to use for the endpoint being configured. * * \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in * ascending order, or bank corruption will occur. @@ -289,22 +199,21 @@ * * \return Boolean \c true if the configuration succeeded, \c false otherwise. */ - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) ATTR_ALWAYS_INLINE; - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) { - return Endpoint_ConfigureEndpoint_Prv(Number, (AVR32_USBB_ALLOC_MASK | - ((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) | - ((uint32_t)(Direction ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) | - ((uint32_t)Banks << AVR32_USBB_EPBK_OFFSET) | - Endpoint_BytesToEPSizeMask(Size)))); + return Endpoint_ConfigureEndpoint_Prv((Address & ENDPOINT_EPNUM_MASK), + (AVR32_USBB_ALLOC_MASK | + ((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) | + ((uint32_t)(Address & ENDPOINT_DIR_IN) ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) | + ((uint32_t)Banks << AVR32_USBB_EPBK_OFFSET) | + Endpoint_BytesToEPSizeMask(Size))); } /** Indicates the number of bytes currently stored in the current endpoint's selected bank. @@ -319,41 +228,51 @@ return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].byct; } + /** Determines the currently selected endpoint's direction. + * + * \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask. + */ + static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Endpoint_GetEndpointDirection(void) + { + return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT); + } + /** 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. + * the currently selected endpoint 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) { - return USB_Endpoint_SelectedEndpoint; + return (USB_Endpoint_SelectedEndpoint | Endpoint_GetEndpointDirection()); } - /** 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). + /** Selects the given endpoint address. * - * Any endpoint operations which do not require the endpoint number to be indicated will operate on + * Any endpoint operations which do not require the endpoint address to be indicated will operate on * the currently selected endpoint. * - * \param[in] EndpointNumber Endpoint number to select. + * \param[in] Address Endpoint address to select. */ - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Endpoint_SelectEndpoint(const uint8_t Address) { - USB_Endpoint_SelectedEndpoint = EndpointNumber; + USB_Endpoint_SelectedEndpoint = (Address & ENDPOINT_EPNUM_MASK); } /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's * data In and Out pointers to the bank's contents. * - * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. + * \param[in] Address Endpoint number whose FIFO buffers are to be reset. */ - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetEndpoint(const uint8_t Address) { + uint32_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK); + AVR32_USBB.uerst |= (AVR32_USBB_EPRST0_MASK << EndpointNumber); AVR32_USBB.uerst &= ~(AVR32_USBB_EPRST0_MASK << EndpointNumber); USB_Endpoint_FIFOPos[EndpointNumber] = &AVR32_USBB_SLAVE[EndpointNumber * ENDPOINT_HSB_ADDRESS_SPACE_SIZE]; @@ -452,8 +371,8 @@ * * \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) + static inline uint32_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint32_t Endpoint_GetEndpointInterrupts(void) { return ((AVR32_USBB.udint & (AVR32_USBB_EP6INT_MASK | AVR32_USBB_EP5INT_MASK | AVR32_USBB_EP4INT_MASK | AVR32_USBB_EP3INT_MASK | @@ -464,14 +383,14 @@ /** 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. + * \param[in] Address Address of the endpoint whose interrupt flag should be tested. * * \return Boolean \c true if the specified endpoint has interrupted, \c 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) + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) { - return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << EndpointNumber)) ? true : false); + return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << (Address & ENDPOINT_EPNUM_MASK))) ? true : false); } /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host. @@ -596,16 +515,6 @@ (&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rstdts = true; } - /** Determines the currently selected endpoint's direction. - * - * \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask. - */ - static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; - static inline uint32_t Endpoint_GetEndpointDirection(void) - { - return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT); - } - /** Sets the direction of the currently selected endpoint. * * \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask. @@ -837,6 +746,20 @@ #endif /* Function Prototypes: */ + /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple + * endpoints at the same time. + * + * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the + * control endpoint. + * + * \param[in] Table Pointer to a table of endpoint descriptions. + * \param[in] Entries Number of entries in the endpoint table to configure. + * + * \return Boolean \c true if all endpoints configured successfully, \c false otherwise. + */ + bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries); + /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically, * with respect to the data direction. This is a convenience function which can be used to * simplify user control request handling. diff --git a/LUFA/Drivers/USB/Core/UC3/Host_UC3.c b/LUFA/Drivers/USB/Core/UC3/Host_UC3.c index 49d43f9b5..932381a14 100644 --- a/LUFA/Drivers/USB/Core/UC3/Host_UC3.c +++ b/LUFA/Drivers/USB/Core/UC3/Host_UC3.c @@ -114,9 +114,7 @@ void USB_Host_ProcessNextHostState(void) HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe); break; case HOST_STATE_Powered_ConfigPipe: - if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, - PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, - PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE))) + if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1))) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; @@ -151,9 +149,7 @@ void USB_Host_ProcessNextHostState(void) HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset); break; case HOST_STATE_Default_PostReset: - if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, - PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP, - USB_Host_ControlPipeSize, PIPE_BANK_SINGLE))) + if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1))) { ErrorCode = HOST_ENUMERROR_PipeConfigError; SubErrorCode = 0; diff --git a/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c b/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c index 4e77a28ff..787244b97 100644 --- a/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c +++ b/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c @@ -43,13 +43,35 @@ uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE; volatile uint32_t USB_Pipe_SelectedPipe = PIPE_CONTROLPIPE; volatile uint8_t* USB_Pipe_FIFOPos[PIPE_TOTAL_PIPES]; -bool Pipe_ConfigurePipe(const uint8_t Number, +bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table, + const uint8_t Entries) +{ + for (uint8_t i = 0; i < Entries; i++) + { + if (!(Table[i].Address)) + continue; + + if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks))) + { + return false; + } + } + + return true; +} + +bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, - const uint8_t Token, - const uint8_t EndpointNumber, + const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks) { + uint8_t Number = (Address & PIPE_EPNUM_MASK); + uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT; + + if (Type == EP_TYPE_CONTROL) + Token = PIPE_TOKEN_SETUP; + USB_Pipe_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * 0x10000]; #if defined(ORDERED_EP_CONFIG) @@ -60,7 +82,7 @@ bool Pipe_ConfigurePipe(const uint8_t Number, (&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | - ((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) | + ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) | Pipe_BytesToEPSizeMask(Size) | ((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); @@ -79,9 +101,9 @@ bool Pipe_ConfigurePipe(const uint8_t Number, UPCFG0Temp = (AVR32_USBB_ALLOC_MASK | ((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) | ((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) | - ((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) | + ((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) | Pipe_BytesToEPSizeMask(Size) | - ((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); + ((EndpointAddress & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET)); } else { diff --git a/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h b/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h index f17fa5376..837afe8b8 100644 --- a/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h +++ b/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h @@ -131,49 +131,22 @@ /** \name Pipe Token Masks */ //@{ - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes), * which will trigger a control request on the attached device when data is written to the pipe. */ #define PIPE_TOKEN_SETUP AVR32_USBB_UPCFG0_PTOKEN_SETUP - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes), * indicating that the pipe data will flow from device to host. */ #define PIPE_TOKEN_IN AVR32_USBB_UPCFG0_PTOKEN_IN - /** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes), + /** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes), * indicating that the pipe data will flow from host to device. */ #define PIPE_TOKEN_OUT AVR32_USBB_UPCFG0_PTOKEN_OUT //@} - /** \name Pipe Bank Mode Masks */ - //@{ - /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe - * should have one single bank, which requires less USB FIFO memory but results in slower transfers as - * only one USB device (the AVR or the attached device) can access the pipe's bank at the one time. - */ - #define PIPE_BANK_SINGLE AVR32_USBB_UPCFG0_PBK_SINGLE - - /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe - * should have two banks, which requires more USB FIFO memory but results in faster transfers as one - * USB device (the AVR or the attached device) can access one bank while the other accesses the second - * bank. - */ - #define PIPE_BANK_DOUBLE AVR32_USBB_UPCFG0_PBK_DOUBLE - - #if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__) - /** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the - * pipe should have three banks, which requires more USB FIFO memory but results in faster transfers - * as one USB device (the AVR or the attached device) can access one bank while the other accesses the - * remaining banks. - * - * \note Not available on all AVR models. - */ - #define PIPE_BANK_TRIPLE AVR32_USBB_UPCFG0_PBK_TRIPLE - #endif - //@} - /** Default size of the default control pipe's bank, until altered by the Endpoint0Size value * in the device descriptor of the attached device. */ @@ -224,6 +197,16 @@ return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].pbyct; } + /** Determines the currently selected pipe's direction. + * + * \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask. + */ + static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline uint8_t Pipe_GetPipeDirection(void) + { + return (((&AVR32_USBB.UPCFG0)[USB_Endpoint_SelectedEndpoint].ptoken == PIPE_TOKEN_OUT) ? PIPE_DIR_OUT : PIPE_DIR_IN); + } + /** 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. * @@ -232,30 +215,32 @@ static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; static inline uint8_t Pipe_GetCurrentPipe(void) { - return USB_Pipe_SelectedPipe; + return (USB_Pipe_SelectedPipe | Pipe_GetPipeDirection()); } - /** Selects the given pipe number. Any pipe operations which do not require the pipe number to be + /** Selects the given pipe address. Any pipe operations which do not require the pipe address to be * indicated will operate on the currently selected pipe. * - * \param[in] PipeNumber Index of the pipe to select. + * \param[in] Address Address 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) + static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Pipe_SelectPipe(const uint8_t Address) { - USB_Pipe_SelectedPipe = PipeNumber; + USB_Pipe_SelectedPipe = (Address & PIPE_EPNUM_MASK); } /** Resets the desired pipe, including the pipe banks and flags. * - * \param[in] PipeNumber Index of the pipe to reset. + * \param[in] Address 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) + static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Pipe_ResetPipe(const uint8_t Address) { + uint32_t PipeNumber = (Address & PIPE_EPNUM_MASK); + AVR32_USBB.uprst |= (AVR32_USBB_PRST0_MASK << PipeNumber); AVR32_USBB.uprst &= ~(AVR32_USBB_PRST0_MASK << PipeNumber); - USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE]; + USB_Pipe_FIFOPos[PipeNumber] = &AVR32_USBB_SLAVE[PipeNumber * PIPE_HSB_ADDRESS_SPACE_SIZE]; } /** Enables the currently selected pipe so that data can be sent and received through it to and from @@ -349,7 +334,7 @@ static inline uint8_t Pipe_GetBoundEndpointAddress(void) { return ((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].pepnum | - ((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_EPDIR_MASK : 0)); + ((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_DIR_IN : PIPE_DIR_OUT)); } /** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds. @@ -376,17 +361,17 @@ AVR32_USBB_P0INT_MASK)) >> AVR32_USBB_P0INT_OFFSET); } - /** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type + /** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type * pipes). * - * \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested. + * \param[in] Address Address of the pipe whose interrupt flag should be tested. * * \return Boolean \c true if the specified pipe has interrupted, \c 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) + static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; + static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) { - return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << PipeNumber)) ? true : false); + return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << (Address & PIPE_EPNUM_MASK))) ? true : false); } /** Unfreezes the selected pipe, allowing it to communicate with an attached device. */ @@ -821,8 +806,22 @@ extern uint8_t USB_Host_ControlPipeSize; /* Function Prototypes: */ - /** Configures the specified pipe number with the given pipe type, token, target endpoint number in the - * attached device, bank size and banking mode. + /** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple + * pipes at the same time. + * + * \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the + * control pipe. + * + * \param[in] Table Pointer to a table of pipe descriptions. + * \param[in] Entries Number of entries in the pipe table to configure. + * + * \return Boolean \c true if all pipes configured successfully, \c false otherwise. + */ + bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table, + const uint8_t Entries); + + /** Configures the specified pipe address with the given pipe type, endpoint address within the attached device, bank size + * and number of hardware banks. * * A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze() * before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or @@ -830,25 +829,19 @@ * numbers of IN requests without automatic freezing - this can be overridden by a call to * \ref Pipe_SetFiniteINRequests(). * - * \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES. - * - * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low - * Speed USB devices - refer to the USB 2.0 specification. + * \param[in] Address Pipe address to configure. * - * \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN. - * All pipes (except Control type) are unidirectional - data may only be read from or - * written to the pipe bank based on its direction, not both. + * \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low + * Speed USB devices - refer to the USB 2.0 specification. * - * \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to. + * \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to. * - * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to - * the USB device, or after they have been received from the USB device (depending on - * the pipe's data direction). The bank size must indicate the maximum packet size that - * the pipe can handle. + * \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to + * the USB device, or after they have been received from the USB device (depending on + * the pipe's data direction). The bank size must indicate the maximum packet size that + * the pipe can handle. * - * \param[in] Banks Number of banks to use for the pipe being configured, a \c PIPE_BANK_* mask. More banks - * uses more USB DPRAM, but offers better performance. Isochronous type pipes <b>must</b> - * have at least two banks. + * \param[in] Banks Number of banks to use for the pipe being configured. * * \note When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order, * or bank corruption will occur. @@ -867,10 +860,9 @@ * * \return Boolean \c true if the configuration succeeded, \c false otherwise. */ - bool Pipe_ConfigurePipe(const uint8_t Number, + bool Pipe_ConfigurePipe(const uint8_t Address, const uint8_t Type, - const uint8_t Token, - const uint8_t EndpointNumber, + const uint8_t EndpointAddress, const uint16_t Size, const uint8_t Banks); diff --git a/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c b/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c index 95ca7d9aa..32772446e 100644 --- a/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c +++ b/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c @@ -191,8 +191,7 @@ static void USB_Init_Device(void) USB_INT_Enable(USB_INT_VBUSTI); Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); USB_INT_Clear(USB_INT_SUSPI); USB_INT_Enable(USB_INT_SUSPI); diff --git a/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c b/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c index d411a9305..a2a5c4a96 100644 --- a/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c +++ b/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c @@ -121,8 +121,7 @@ ISR(USB_GEN_vect) USB_Device_SetDeviceAddress(0); Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); #if defined(INTERRUPT_CONTROL_ENDPOINT) USB_INT_Enable(USB_INT_RXSTPI); diff --git a/LUFA/Drivers/USB/Core/USBController.h b/LUFA/Drivers/USB/Core/USBController.h index a91e18c27..44a10e371 100644 --- a/LUFA/Drivers/USB/Core/USBController.h +++ b/LUFA/Drivers/USB/Core/USBController.h @@ -81,6 +81,24 @@ #define ENDPOINT_DIR_IN 0x80 //@} + /** \name Pipe Direction Masks */ + //@{ + /** Pipe direction mask, for masking against pipe addresses to retrieve the pipe's + * direction for comparing with the \c PIPE_DIR_* masks. + */ + #define PIPE_DIR_MASK 0x80 + + /** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with + * the index of the address within a device to obtain the full endpoint address. + */ + #define PIPE_DIR_OUT 0x00 + + /** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with + * the index of the address within a device to obtain the full endpoint address. + */ + #define PIPE_DIR_IN 0x80 + //@} + /** \name Endpoint/Pipe Type Masks */ //@{ /** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared diff --git a/LUFA/Drivers/USB/Core/USBMode.h b/LUFA/Drivers/USB/Core/USBMode.h index bc2f86dd5..f62c8c152 100644 --- a/LUFA/Drivers/USB/Core/USBMode.h +++ b/LUFA/Drivers/USB/Core/USBMode.h @@ -137,6 +137,16 @@ */ #define USB_SERIES_B3_XMEGA + /** Indicates that the target AVR microcontroller belongs to the XMEGA C3 Series USB controller + * (i.e. ATXMEGA*C3) when defined. + */ + #define USB_SERIES_C3_XMEGA + + /** Indicates that the target AVR microcontroller belongs to the XMEGA C4 Series USB controller + * (i.e. ATXMEGA*C4) when defined. + */ + #define USB_SERIES_C4_XMEGA + /** Indicates that the target microcontroller and compilation settings allow for the * target to be configured in USB Device mode when defined. */ @@ -219,6 +229,14 @@ #elif (defined(__AVR_ATxmega128B3__) || defined(__AVR_ATxmega64B3__)) #define USB_SERIES_B3_XMEGA #define USB_CAN_BE_DEVICE + #elif (defined(__AVR_ATxmega128C3__) || defined(__AVR_ATxmega64C3__) || \ + defined(__AVR_ATxmega192C3__) || defined(__AVR_ATxmega256C3__) || \ + defined(__AVR_ATxmega384C3__)) + #define USB_SERIES_C3_XMEGA + #define USB_CAN_BE_DEVICE + #elif (defined(__AVR_ATxmega16C4__) || defined(__AVR_ATxmega32C4__)) + #define USB_SERIES_C4_XMEGA + #define USB_CAN_BE_DEVICE #endif #if (defined(USB_CAN_BE_DEVICE) && defined(USB_CAN_BE_HOST)) diff --git a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h index 85be0f1bf..4d75cc2a2 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h @@ -92,10 +92,12 @@ */ #define USB_DEVICE_OPT_LOWSPEED (1 << 0) - /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the - * USB interface should be initialized in full speed (12Mb/s) mode. - */ - #define USB_DEVICE_OPT_FULLSPEED (0 << 0) + #if (F_USB > 6000000) + /** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the + * USB interface should be initialized in full speed (12Mb/s) mode. + */ + #define USB_DEVICE_OPT_FULLSPEED (0 << 0) + #endif //@} #if (!defined(NO_INTERNAL_SERIAL) || defined(__DOXYGEN__)) @@ -157,7 +159,7 @@ static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT; static inline uint16_t USB_Device_GetFrameNumber(void) { - return USB_EndpointTable.FrameNum; + return ((USB_EndpointTable_t*)USB.EPPTR)->FrameNum; } #if !defined(NO_SOF_EVENTS) diff --git a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c index 98e35e59a..1aeb985f8 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c +++ b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c @@ -48,20 +48,36 @@ volatile uint8_t USB_Endpoint_SelectedEndpoint; volatile USB_EP_t* USB_Endpoint_SelectedHandle; volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO; -bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number, - const uint8_t Direction, +bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries) +{ + for (uint8_t i = 0; i < Entries; i++) + { + if (!(Table[i].Address)) + continue; + + if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks))) + { + return false; + } + } + + return true; +} + +bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address, const uint8_t Config, const uint8_t Size) { - Endpoint_SelectEndpoint(Number | Direction); + Endpoint_SelectEndpoint(Address); USB_Endpoint_SelectedHandle->CTRL = 0; - USB_Endpoint_SelectedHandle->STATUS = (Direction == ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0; + USB_Endpoint_SelectedHandle->STATUS = (Address & ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0; USB_Endpoint_SelectedHandle->CTRL = Config; USB_Endpoint_SelectedHandle->CNT = 0; USB_Endpoint_SelectedHandle->DATAPTR = (intptr_t)USB_Endpoint_SelectedFIFO->Data; - USB_Endpoint_SelectedFIFO->Length = (Direction == ENDPOINT_DIR_IN) ? Size : 0; + USB_Endpoint_SelectedFIFO->Length = (Address & ENDPOINT_DIR_IN) ? Size : 0; USB_Endpoint_SelectedFIFO->Position = 0; return true; @@ -71,8 +87,8 @@ void Endpoint_ClearEndpoints(void) { for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++) { - USB_EndpointTable.Endpoints[EPNum].IN.CTRL = 0; - USB_EndpointTable.Endpoints[EPNum].OUT.CTRL = 0; + ((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].IN.CTRL = 0; + ((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].OUT.CTRL = 0; } } diff --git a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h index 7828f308a..720b5f3b4 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h @@ -88,14 +88,20 @@ #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__) + /* Public Interface - May be used in end-application: */ /* Macros: */ - #define _ENDPOINT_GET_MAXSIZE(EPIndex) 1023 - #define _ENDPOINT_GET_BANKS(EPIndex) 2 - - #define ENDPOINT_DETAILS_MAXEP 16 + #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__) + /** Total number of endpoints (including the default control endpoint at address 0) which may + * be used in the device. Different USB AVR models support different amounts of endpoints, + * this value reflects the maximum number of endpoints for the currently selected AVR model. + */ + #define ENDPOINT_TOTAL_ENDPOINTS 16 + #else + #define ENDPOINT_TOTAL_ENDPOINTS 1 + #endif + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) /* Type Defines: */ typedef struct { @@ -112,7 +118,7 @@ } Endpoint_FIFOPair_t; /* External Variables: */ - extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_DETAILS_MAXEP]; + extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS]; extern volatile uint8_t USB_Endpoint_SelectedEndpoint; extern volatile USB_EP_t* USB_Endpoint_SelectedHandle; extern volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO; @@ -135,8 +141,7 @@ } /* Function Prototypes: */ - bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number, - const uint8_t Direction, + bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address, const uint8_t Config, const uint8_t Size); void Endpoint_ClearEndpoints(void); @@ -144,23 +149,6 @@ /* Public Interface - May be used in end-application: */ /* Macros: */ - /** \name Endpoint Bank Mode Masks */ - //@{ - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have one single bank, which requires less USB FIFO memory but results - * in slower transfers as only one USB device (the AVR or the host) can access the endpoint's - * bank at the one time. - */ - #define ENDPOINT_BANK_SINGLE 0 - - /** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates - * that the endpoint should have two banks, which requires more USB FIFO memory but results - * in faster transfers as one USB device (the AVR or the host) can access one bank while the other - * accesses the second bank. - */ - #define ENDPOINT_BANK_DOUBLE USB_EP_PINGPONG_bm - //@} - #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) /** Default size of the default control endpoint's bank, until altered by the control endpoint bank size * value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined. @@ -168,34 +156,6 @@ #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8 #endif - /** Retrieves the maximum bank size in bytes of a given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex) - - /** Retrieves the total number of banks supported by the given endpoint. - * - * \attention This macro will only work correctly on endpoint indexes that are compile-time constants - * defined by the preprocessor. - * - * \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1) - */ - #define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex) - - #if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__) - /** Total number of endpoints (including the default control endpoint at address 0) which may - * be used in the device. Different USB AVR models support different amounts of endpoints, - * this value reflects the maximum number of endpoints for the currently selected AVR model. - */ - #define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP - #else - #define ENDPOINT_TOTAL_ENDPOINTS 1 - #endif - /* Enums: */ /** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function. * @@ -221,54 +181,47 @@ }; /* Inline Functions: */ - /** 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). + /** Selects the given endpoint address. * - * Any endpoint operations which do not require the endpoint number to be indicated will operate on + * Any endpoint operations which do not require the endpoint address to be indicated will operate on * the currently selected endpoint. * - * \param[in] EndpointNumber Endpoint number to select. + * \param[in] Address Endpoint address to select. */ - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber); - static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_SelectEndpoint(const uint8_t Address); + static inline void Endpoint_SelectEndpoint(const uint8_t Address) { - USB_Endpoint_SelectedEndpoint = EndpointNumber; + uint8_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK); + + USB_Endpoint_SelectedEndpoint = Address; - if (EndpointNumber & ENDPOINT_DIR_IN) + if (Address & ENDPOINT_DIR_IN) { - USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN; - USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].IN; + USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].IN; + USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].IN; } else { - USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT; - USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT; + USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].OUT; + USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].OUT; } } - /** Configures the specified endpoint number with the given endpoint type, direction, bank size + /** Configures the specified endpoint address with the given endpoint type, direction, bank size * and banking mode. Once configured, the endpoint may be read from or written to, depending * on its direction. * - * \param[in] Number Endpoint number to configure. This must be more than 0 and less than - * \ref ENDPOINT_TOTAL_ENDPOINTS. + * \param[in] Address Endpoint address to configure. * * \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types * are available on Low Speed USB devices - refer to the USB 2.0 specification. * - * \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN. - * All endpoints (except Control type) are unidirectional - data may only be read - * from or written to the endpoint bank based on its direction, not both. - * * \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted * to the USB host, or after they have been received from the USB host (depending on * the endpoint's data direction). The bank size must indicate the maximum packet size * that the endpoint can handle. * - * \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask. - * More banks uses more USB DPRAM, but offers better performance. Isochronous type - * endpoints <b>must</b> have at least two banks. + * \param[in] Banks Number of hardware banks to use for the endpoint being configured. * * \note The default control endpoint should not be manually configured by the user application, as * it is automatically configured by the library internally. @@ -278,21 +231,19 @@ * * \return Boolean \c true if the configuration succeeded, \c false otherwise. */ - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) ATTR_ALWAYS_INLINE; - static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number, + static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address, const uint8_t Type, - const uint8_t Direction, const uint16_t Size, const uint8_t Banks) { - uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | Banks | Endpoint_BytesToEPSizeMask(Size)); + uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | ((Banks > 1) ? USB_EP_PINGPONG_bm : 0) | Endpoint_BytesToEPSizeMask(Size)); // TODO - Fix once limitations are lifted - if ((Banks != ENDPOINT_BANK_SINGLE) || (Size > 64)) + if ((Banks > 1) || (Size > 64)) return false; switch (Type) @@ -309,9 +260,9 @@ } if (Type == EP_TYPE_CONTROL) - Endpoint_ConfigureEndpoint_PRV(Number, (Direction ^ ENDPOINT_DIR_IN), EPConfigMask, Size); + Endpoint_ConfigureEndpoint_PRV(Address ^ ENDPOINT_DIR_IN, EPConfigMask, Size); - return Endpoint_ConfigureEndpoint_PRV(Number, Direction, EPConfigMask, Size); + return Endpoint_ConfigureEndpoint_PRV(Address, EPConfigMask, Size); } /** Indicates the number of bytes currently stored in the current endpoint's selected bank. @@ -327,8 +278,8 @@ } /** 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. + * the currently selected endpoint so that it can be restored after another endpoint has been + * manipulated. * * \return Index of the currently selected endpoint. */ @@ -341,15 +292,15 @@ /** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's * data In and Out pointers to the bank's contents. * - * \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset. + * \param[in] Address Endpoint address whose FIFO buffers are to be reset. */ - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE; - static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) + static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE; + static inline void Endpoint_ResetEndpoint(const uint8_t Address) { - if (EndpointNumber & ENDPOINT_DIR_IN) - USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN.Position = 0; + if (Address & ENDPOINT_DIR_IN) + USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].IN.Position = 0; else - USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT.Position = 0; + USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].OUT.Position = 0; } /** Determines if the currently selected endpoint is enabled, but not necessarily configured. @@ -388,10 +339,7 @@ static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE; static inline bool Endpoint_IsReadWriteAllowed(void) { - if (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN) - return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length); - else - return (USB_Endpoint_SelectedFIFO->Position > 0); + return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length); } /** Determines if the currently selected endpoint is configured. @@ -404,32 +352,6 @@ return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) ? 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 <tt>(1 << <i>{Endpoint Number}</i>)</tt>. - * - * \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 0; // TODO - } - - /** 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 \c true if the specified endpoint has interrupted, \c 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) - { - (void)EndpointNumber; - return 0; // TODO - } - /** Determines if the selected IN endpoint is ready for a new packet to be sent to the host. * * \ingroup Group_EndpointPacketManagement_XMEGA @@ -800,6 +722,20 @@ #endif /* Function Prototypes: */ + /** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple + * endpoints at the same time. + * + * \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the + * control endpoint. + * + * \param[in] Table Pointer to a table of endpoint descriptions. + * \param[in] Entries Number of entries in the endpoint table to configure. + * + * \return Boolean \c true if all endpoints configured successfully, \c false otherwise. + */ + bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table, + const uint8_t Entries); + /** Completes the status stage of a control transfer on a CONTROL type endpoint automatically, * with respect to the data direction. This is a convenience function which can be used to * simplify user control request handling. diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c index 387e8e417..844ef650f 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c +++ b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c @@ -43,7 +43,8 @@ volatile uint8_t USB_CurrentMode = USB_MODE_None; volatile uint8_t USB_Options; #endif -USB_EndpointTable_t USB_EndpointTable ATTR_ALIGNED(4); +/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */ +uint8_t USB_EndpointTable[sizeof(USB_EndpointTable_t) + 1]; void USB_Init( #if defined(USB_CAN_BE_BOTH) @@ -75,8 +76,9 @@ void USB_Init( USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1)); NVM.CMD = 0; - USB.EPPTR = (intptr_t)&USB_EndpointTable; - USB.CTRLA = (USB_STFRNUM_bm | USB_MAXEP_gm); + /* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */ + USB.EPPTR = ((intptr_t)&USB_EndpointTable[1] & ~(1 << 0)); + USB.CTRLA = (USB_STFRNUM_bm | ((ENDPOINT_TOTAL_ENDPOINTS - 1) << USB_MAXEP_gp)); if ((USB_Options & USB_OPT_BUSEVENT_PRIHIGH) == USB_OPT_BUSEVENT_PRIHIGH) USB.INTCTRLA = (3 << USB_INTLVL_gp); @@ -103,13 +105,17 @@ void USB_Disable(void) void USB_ResetInterface(void) { + #if defined(USB_DEVICE_OPT_FULLSPEED) if (USB_Options & USB_DEVICE_OPT_LOWSPEED) CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); else CLK.USBCTRL = (((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp); - + #else + CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp); + #endif + if (USB_Options & USB_OPT_PLLCLKSRC) - CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm); + CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm); else CLK.USBCTRL |= (CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm); @@ -172,8 +178,7 @@ static void USB_Init_Device(void) USB_Device_SetFullSpeed(); Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); USB_INT_Enable(USB_INT_BUSEVENTI); diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h index 2f14f758a..25402e855 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h +++ b/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h @@ -69,7 +69,7 @@ } ATTR_PACKED USB_EndpointTable_t; /* External Variables: */ - extern USB_EndpointTable_t USB_EndpointTable; + extern uint8_t USB_EndpointTable[]; #endif @@ -95,7 +95,7 @@ #error F_USB is not defined. You must define F_USB to the frequency of the unprescaled USB controller clock in your project makefile. #endif - #if (F_USB % 6000000) + #if ((F_USB % 6000000) || (F_USB < 6000000)) #error Invalid F_USB specified. F_USB must be a multiple of 6MHz for USB Low Speed operation, and a multiple of 48MHz for Full Speed operation. #endif diff --git a/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c b/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c index b0e52d06e..3554165c1 100644 --- a/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c +++ b/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c @@ -97,8 +97,7 @@ ISR(USB_BUSEVENT_vect) Endpoint_ClearEndpoints(); Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL, - ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize, - ENDPOINT_BANK_SINGLE); + USB_Device_ControlEndpointSize, 1); EVENT_USB_Device_Reset(); } |