From 74298f8ca11dc8d3b0359d1d4e124d6494c3eeac Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Fri, 10 Apr 2009 01:15:42 +0200 Subject: * digital/avr/modules/usb: - imported LUFA. --- .../usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h | 842 +++++++++++++++++++++ 1 file changed, 842 insertions(+) create mode 100644 digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h (limited to 'digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h') diff --git a/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h new file mode 100644 index 00000000..5f317041 --- /dev/null +++ b/digital/avr/modules/usb/lufa/LUFA/Drivers/USB/LowLevel/Endpoint.h @@ -0,0 +1,842 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2009. + + dean [at] fourwalledcubicle [dot] com + www.fourwalledcubicle.com +*/ + +/* + Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com) + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose and without fee is hereby + granted, provided that the above copyright notice appear in all + copies and that both that the copyright notice and this + permission notice and warranty disclaimer appear in supporting + documentation, and that the name of the author not be used in + advertising or publicity pertaining to distribution of the + software without specific, written prior permission. + + The author disclaim all warranties with regard to this + software, including all implied warranties of merchantability + and fitness. In no event shall the author be liable for any + special, indirect or consequential damages or any damages + whatsoever resulting from loss of use, data or profits, whether + in an action of contract, negligence or other tortious action, + arising out of or in connection with the use or performance of + this software. +*/ + +/** \file + * + * Functions, macros and enums related to endpoint management when in USB Device mode. This + * module contains the endpoint management macros, as well as endpoint interrupt and data + * send/recieve functions for various datatypes. + */ + +#ifndef __ENDPOINT_H__ +#define __ENDPOINT_H__ + + /* Includes: */ + #include + #include + + #include "../../../Common/Common.h" + #include "../HighLevel/USBTask.h" + + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + #include "StreamCallbacks.h" + #endif + /* Enable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + extern "C" { + #endif + + /* Public Interface - May be used in end-application: */ + /* Macros: */ + /** Endpoint data direction mask for Endpoint_ConfigureEndpoint(). This indicates that the endpoint + * should be initialized in the OUT direction - i.e. data flows from host to device. + */ + #define ENDPOINT_DIR_OUT 0 + + /** Endpoint data direction mask for Endpoint_ConfigureEndpoint(). This indicates that the endpoint + * should be initialized in the IN direction - i.e. data flows from device to host. + */ + #define ENDPOINT_DIR_IN (1 << EPDIR) + + /** Mask for the bank mode selection for the 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 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) + + /** Endpoint address for the default control endpoint, which always resides in address 0. This is + * defined for convenience to give more readable code when used with the endpoint macros. + */ + #define ENDPOINT_CONTROLEP 0 + + /** Default size of the default control endpoint's bank, until altered by the Endpoint0Size value + * in the device descriptor. Not available if the FIXED_CONTROL_ENDPOINT_SIZE token is defined. + */ + #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) + #define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8 + #endif + + /** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's + * numerical address in the device. + */ + #define ENDPOINT_EPNUM_MASK 0b111 + + /** Endpoint bank size mask, for masking against endpoint addresses to retrieve the endpoint's + * bank size in the device. + */ + #define ENDPOINT_EPSIZE_MASK 0x7FF + + /** Maximum size in bytes of a given endpoint. + * + * \param n Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1) + */ + #define ENDPOINT_MAX_SIZE(n) _ENDPOINT_GET_MAXSIZE(n) + + /** Indicates if the given endpoint supports double banking. + * + * \param n Endpoint number, a value between 0 and (ENDPOINT_TOTAL_ENDPOINTS - 1) + */ + #define ENDPOINT_DOUBLEBANK_SUPPORTED(n) _ENDPOINT_GET_DOUBLEBANK(n) + + #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || 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 7 + #else + #define ENDPOINT_TOTAL_ENDPOINTS 5 + #endif + + /** Interrupt definition for the endpoint SETUP interrupt (for CONTROL type endpoints). Should be + * used with the USB_INT_* macros located in USBInterrupt.h. + * + * This interrupt will fire if enabled on a CONTROL type endpoint if a new control packet is + * received from the host. + */ + #define ENDPOINT_INT_SETUP UEIENX, (1 << RXSTPE), UEINTX, (1 << RXSTPI) + + /** Interrupt definition for the endpoint IN interrupt (for INTERRUPT type endpoints). Should be + * used with the USB_INT_* macros located in USBInterrupt.h. + * + * This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt + * period has elapsed and the endpoint is ready for a new packet to be written to its FIFO buffer + * (if required). + */ + #define ENDPOINT_INT_IN UEIENX, (1 << TXINE) , UEINTX, (1 << TXINI) + + /** Interrupt definition for the endpoint OUT interrupt (for INTERRUPT type endpoints). Should be + * used with the USB_INT_* macros located in USBInterrupt.h. + * + * This interrupt will fire if enabled on an INTERRUPT type endpoint if a the endpoint interrupt + * period has elapsed and the endpoint is ready for a packet from the host to be read from its + * FIFO buffer (if received). + */ + #define ENDPOINT_INT_OUT UEIENX, (1 << RXOUTE), UEINTX, (1 << RXOUTI) + + #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) || defined(__DOXYGEN__) + /** Indicates the number of bytes currently stored in the current endpoint's selected bank. */ + #define Endpoint_BytesInEndpoint() UEBCX + #else + #define Endpoint_BytesInEndpoint() UEBCLX + #endif + + /** Returns 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. + */ + #define Endpoint_GetCurrentEndpoint() (UENUM & ENDPOINT_EPNUM_MASK) + + /** Selects the given endpoint number. If the address from the device descriptors is used, the + * value should be masked with the 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. + */ + #define Endpoint_SelectEndpoint(epnum) MACROS{ UENUM = epnum; }MACROE + + /** 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. + */ + #define Endpoint_ResetFIFO(epnum) MACROS{ UERST = (1 << epnum); UERST = 0; }MACROE + + /** 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 rather than just being enabled via the + * Endpoint_ConfigureEndpoint() macro, which calls Endpoint_EnableEndpoint() automatically. + */ + #define Endpoint_EnableEndpoint() MACROS{ UECONX |= (1 << EPEN); }MACROE + + /** Disables the currently selected endpoint so that data cannot be sent and received through it + * to and from a host. + */ + #define Endpoint_DisableEndpoint() MACROS{ UECONX &= ~(1 << EPEN); }MACROE + + /** Returns true if the currently selected endpoint is enabled, false otherwise. */ + #define Endpoint_IsEnabled() ((UECONX & (1 << EPEN)) ? true : false) + + /** Returns true 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 occured in the endpoint, or if + * the endpoint is an OUT direction and no packet has been received, or if the endpoint is an IN + * direction and the endpoint bank is full. + */ + #define Endpoint_ReadWriteAllowed() ((UEINTX & (1 << RWAL)) ? true : false) + + /** Returns true if the currently selected endpoint is configured, false otherwise. */ + #define Endpoint_IsConfigured() ((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}). + */ + #define Endpoint_GetEndpointInterrupts() UEINT + + /** Clears the endpoint interrupt flag. This clears the specified endpoint number's interrupt + * mask in the endpoint interrupt flag register. + */ + #define Endpoint_ClearEndpointInterrupt(n) MACROS{ UEINT &= ~(1 << n); }MACROE + + /** Returns true if the specified endpoint number has interrupted (valid only for INTERRUPT type + * endpoints), false otherwise. + */ + #define Endpoint_HasEndpointInterrupted(n) ((UEINT & (1 << n)) ? true : false) + + /** Clears the currently selected endpoint bank, and switches to the alternate bank if the currently + * selected endpoint is dual-banked. When cleared, this either frees the bank up for the next packet + * from the host (if the endpoint is of the OUT direction) or sends the packet contents to the host + * (if the endpoint is of the IN direction). + */ + #define Endpoint_ClearCurrentBank() MACROS{ UEINTX &= ~(1 << FIFOCON); }MACROE + + /** Returns true if the current CONTROL type endpoint is ready for an IN packet, false otherwise. */ + #define Endpoint_IsSetupINReady() ((UEINTX & (1 << TXINI)) ? true : false) + + /** Returns true if the current CONTROL type endpoint is ready for an OUT packet, false otherwise. */ + #define Endpoint_IsSetupOUTReceived() ((UEINTX & (1 << RXOUTI)) ? true : false) + + /** Returns true if the current CONTROL type endpoint is ready for a SETUP packet, false otherwise. */ + #define Endpoint_IsSetupReceived() ((UEINTX & (1 << RXSTPI)) ? true : false) + + /** Clears a received SETUP packet on the currently selected CONTROL type endpoint. */ + #define Endpoint_ClearSetupReceived() MACROS{ UEINTX &= ~(1 << RXSTPI); }MACROE + + /** Sends an IN packet to the host on the currently selected CONTROL type endpoint. */ + #define Endpoint_ClearSetupIN() MACROS{ UEINTX &= ~(1 << TXINI); }MACROE + + /** Acknowedges an OUT packet to the host on the currently selected CONTROL type endpoint, freeing + * up the endpoint for the next packet. + */ + #define Endpoint_ClearSetupOUT() MACROS{ UEINTX &= ~(1 << RXOUTI); }MACROE + + /** Stalls the current endpoint, indicating to the host that a logical problem occured 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 seqeuence. + * + * The currently selected endpoint remains stalled until either the Endpoint_ClearStall() macro + * is called, or the host issues a CLEAR FEATURE request to the device for the currently selected + * endpoint. + */ + #define Endpoint_StallTransaction() MACROS{ UECONX |= (1 << STALLRQ); }MACROE + + /** Clears the stall on the currently selected endpoint. */ + #define Endpoint_ClearStall() MACROS{ UECONX |= (1 << STALLRQC); }MACROE + + /** Returns true if the currently selected endpoint is stalled, false othewise. */ + #define Endpoint_IsStalled() ((UECONX & (1 << STALLRQ)) ? true : false) + + /** Resets the data toggle of the currently selected endpoint. */ + #define Endpoint_ResetDataToggle() MACROS{ UECONX |= (1 << RSTDT); }MACROE + + /* Enums: */ + /** Enum for the possible error return codes of the Endpoint_WaitUntilReady function */ + enum Endpoint_WaitUntilReady_ErrorCodes_t + { + ENDPOINT_READYWAIT_NoError = 0, /**< Endpoint is ready for next packet, no error. */ + ENDPOINT_READYWAIT_EndpointStalled = 1, /**< The endpoint was stalled during the stream + * transfer by the host or device. + */ + ENDPOINT_READYWAIT_DeviceDisconnected = 2, /**< Device was disconnected from the host while + * waiting for the endpoint to become ready. + */ + ENDPOINT_READYWAIT_Timeout = 3, /**< The host failed to accept or send the next packet + * within the software timeout period set by the + * USB_STREAM_TIMEOUT_MS macro. + */ + }; + + /** Enum for the possible error return codes of the Endpoint_*_Stream_* functions. */ + enum Endpoint_Stream_RW_ErrorCodes_t + { + ENDPOINT_RWSTREAM_ERROR_NoError = 0, /**< Command completed successfully, no error. */ + ENDPOINT_RWSTREAM_ERROR_EndpointStalled = 1, /**< The endpoint was stalled during the stream + * transfer by the host or device. + */ + ENDPOINT_RWSTREAM_ERROR_DeviceDisconnected = 1, /**< Device was disconnected from the host during + * the transfer. + */ + ENDPOINT_RWSTREAM_ERROR_Timeout = 2, /**< The host failed to accept or send the next packet + * within the software timeout period set by the + * USB_STREAM_TIMEOUT_MS macro. + */ + ENDPOINT_RWSTREAM_ERROR_CallbackAborted = 3, /**< Indicates that the stream's callback function + * aborted the transfer early. + */ + }; + + /** Enum for the possible error return codes of the Endpoint_*_Control_Stream_* functions. */ + enum Endpoint_ControlStream_RW_ErrorCodes_t + { + ENDPOINT_RWCSTREAM_ERROR_NoError = 0, /**< Command completed successfully, no error. */ + ENDPOINT_RWCSTREAM_ERROR_HostAborted = 1, /**< The aborted the transfer prematurely. */ + }; + + /* Inline Functions: */ + /** Reads one byte from the currently selected endpoint's bank, for OUT direction endpoints. */ + static inline uint8_t Endpoint_Read_Byte(void) ATTR_WARN_UNUSED_RESULT; + static inline uint8_t Endpoint_Read_Byte(void) + { + return UEDATX; + } + + /** Writes one byte from the currently selected endpoint's bank, for IN direction endpoints. */ + static inline void Endpoint_Write_Byte(const uint8_t Byte) + { + UEDATX = Byte; + } + + /** Discards one byte from the currently selected endpoint's bank, for OUT direction endpoints. */ + static inline void Endpoint_Discard_Byte(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + } + + /** Reads two bytes from the currently selected endpoint's bank in little endian format, for OUT + * direction endpoints. + */ + static inline uint16_t Endpoint_Read_Word_LE(void) ATTR_WARN_UNUSED_RESULT; + static inline uint16_t Endpoint_Read_Word_LE(void) + { + uint16_t Data; + + Data = UEDATX; + Data |= (((uint16_t)UEDATX) << 8); + + return Data; + } + + /** Reads two bytes from the currently selected endpoint's bank in big endian format, for OUT + * direction endpoints. + */ + static inline uint16_t Endpoint_Read_Word_BE(void) ATTR_WARN_UNUSED_RESULT; + static inline uint16_t Endpoint_Read_Word_BE(void) + { + uint16_t Data; + + Data = (((uint16_t)UEDATX) << 8); + Data |= UEDATX; + + return Data; + } + + /** Writes two bytes to the currently selected endpoint's bank in little endian format, for IN + * direction endpoints. + */ + static inline void Endpoint_Write_Word_LE(const uint16_t Word) + { + UEDATX = (Word & 0xFF); + UEDATX = (Word >> 8); + } + + /** Writes two bytes to the currently selected endpoint's bank in big endian format, for IN + * direction endpoints. + */ + static inline void Endpoint_Write_Word_BE(const uint16_t Word) + { + UEDATX = (Word >> 8); + UEDATX = (Word & 0xFF); + } + + /** Discards two bytes from the currently selected endpoint's bank, for OUT direction endpoints. */ + static inline void Endpoint_Discard_Word(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + Dummy = UEDATX; + } + + /** Reads four bytes from the currently selected endpoint's bank in little endian format, for OUT + * direction endpoints. + */ + static inline uint32_t Endpoint_Read_DWord_LE(void) ATTR_WARN_UNUSED_RESULT; + static inline uint32_t Endpoint_Read_DWord_LE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[0] = UEDATX; + Data.Bytes[1] = UEDATX; + Data.Bytes[2] = UEDATX; + Data.Bytes[3] = UEDATX; + + return Data.DWord; + } + + /** Reads four bytes from the currently selected endpoint's bank in big endian format, for OUT + * direction endpoints. + */ + static inline uint32_t Endpoint_Read_DWord_BE(void) ATTR_WARN_UNUSED_RESULT; + static inline uint32_t Endpoint_Read_DWord_BE(void) + { + union + { + uint32_t DWord; + uint8_t Bytes[4]; + } Data; + + Data.Bytes[3] = UEDATX; + Data.Bytes[2] = UEDATX; + Data.Bytes[1] = UEDATX; + Data.Bytes[0] = UEDATX; + + return Data.DWord; + } + + /** Writes four bytes to the currently selected endpoint's bank in little endian format, for IN + * direction endpoints. + */ + static inline void Endpoint_Write_DWord_LE(const uint32_t DWord) + { + Endpoint_Write_Word_LE(DWord); + Endpoint_Write_Word_LE(DWord >> 16); + } + + /** Writes four bytes to the currently selected endpoint's bank in big endian format, for IN + * direction endpoints. + */ + static inline void Endpoint_Write_DWord_BE(const uint32_t DWord) + { + Endpoint_Write_Word_BE(DWord >> 16); + Endpoint_Write_Word_BE(DWord); + } + + /** Discards four bytes from the currently selected endpoint's bank, for OUT direction endpoints. */ + static inline void Endpoint_Discard_DWord(void) + { + uint8_t Dummy; + + Dummy = UEDATX; + Dummy = UEDATX; + Dummy = UEDATX; + Dummy = UEDATX; + } + + /* External Variables: */ + /** Global indicating the maximum packet size of the default control endpoint located at address + * 0 in the device. This value is set to the value indicated in the device descriptor in the user + * project once the USB interface is initialized into device mode. + * + * If space is an issue, it is possible to fix this to a static value by defining the control + * endpoint size in the FIXED_CONTROL_ENDPOINT_SIZE token passed to the compiler in the makefile + * via the -D switch. When a fixed control endpoint size is used, the size is no longer dynamically + * read from the descriptors at runtime and instead fixed to the given value. When used, it is + * important that the descriptor control endpoint size value matches the size given as the + * FIXED_CONTROL_ENDPOINT_SIZE token - it is recommended that the FIXED_CONTROL_ENDPOINT_SIZE token + * be used in the descriptors to ensure this. + * + * \note This variable should be treated as read-only in the user application, and never manually + * changed in value. + */ + #if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__)) + extern uint8_t USB_ControlEndpointSize; + #else + #define USB_ControlEndpointSize FIXED_CONTROL_ENDPOINT_SIZE + #endif + + /* Function Prototypes: */ + /** Configures the specified endpoint number with the given endpoint type, direction, bank size + * and banking mode. Endpoints should be allocated in ascending order by their address in the + * device (i.e. endpoint 1 should be configured before endpoint 2 and so on). + * + * The endpoint type may be one of the EP_TYPE_* macros listed in LowLevel.h and the direction + * may be either ENDPOINT_DIR_OUT or ENDPOINT_DIR_IN. + * + * The bank size must indicate the maximum packet size that the endpoint can handle. Different + * endpoint numbers can handle different maximum packet sizes - refer to the chosen USB AVR's + * datasheet to determine the maximum bank size for each endpoint. + * + * The banking mode may be either ENDPOINT_BANK_SINGLE or ENDPOINT_BANK_DOUBLE. + * + * The success of this routine can be determined via the Endpoint_IsConfigured() macro. + * + * By default, the routine is entirely dynamic, and will accept both constant and variable inputs. + * If dynamic configuration is unused, a small space savings can be made by defining the + * STATIC_ENDPOINT_CONFIGURATION macro via the -D switch to the compiler, to optimize for constant + * input values. + * + * \note This routine will select the specified endpoint, and the endpoint will remain selected + * once the routine completes regardless of if the endpoint configuration succeeds. + * + * \return Boolean true if the configuration succeeded, false otherwise + */ + bool Endpoint_ConfigureEndpoint(const uint8_t Number, const uint8_t Type, const uint8_t Direction, + const uint16_t Size, const uint8_t Banks); + + /** Spinloops until the currently selected non-control endpoint is ready for the next packet of data + * to be read or written to it. + * + * \note This routine should not be called on CONTROL type endpoints. + * + * \return A value from the Endpoint_WaitUntilReady_ErrorCodes_t enum. + */ + uint8_t Endpoint_WaitUntilReady(void); + + /** Reads and discards the given number of bytes from the endpoint from the given buffer, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the next + * packet is ready, allowing for early aborts of stream transfers. + * + * The callback routine should be created using the STREAM_CALLBACK() macro. If the token + * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled + * and this function has the Callback parameter ommitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param Length Number of bytes to send via the currently selected endpoint. + * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback + * + * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Discard_Stream(uint16_t Length + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + , uint8_t (* const Callback)(void) + #endif + ); + + /** Writes the given number of bytes to the endpoint from the given buffer in little endian, + * sending full packets to the host as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * Endpoint_ClearCurrentBank() macro. Between each USB packet, the given stream callback function + * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early + * aborts of stream transfers. + * + * The callback routine should be created using the STREAM_CALLBACK() macro. If the token + * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled + * and this function has the Callback parameter ommitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param Buffer Pointer to the source data buffer to read from. + * \param Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback + * + * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Stream_LE(const void* Buffer, uint16_t Length + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + , uint8_t (* const Callback)(void) + #endif + ) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the endpoint from the given buffer in big endian, + * sending full packets to the host as needed. The last packet filled is not automatically sent; + * the user is responsible for manually sending the last written packet to the host via the + * Endpoint_ClearCurrentBank() macro. Between each USB packet, the given stream callback function + * is executed repeatedly until the endpoint is ready to accept the next packet, allowing for early + * aborts of stream transfers. + * + * The callback routine should be created using the STREAM_CALLBACK() macro. If the token + * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled + * and this function has the Callback parameter ommitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param Buffer Pointer to the source data buffer to read from. + * \param Length Number of bytes to read for the currently selected endpoint into the buffer. + * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback + * + * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Stream_BE(const void* Buffer, uint16_t Length + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + , uint8_t (* const Callback)(void) + #endif + ) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the endpoint from the given buffer in little endian, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the endpoint + * is ready to accept the next packet, allowing for early aborts of stream transfers. + * + * The callback routine should be created using the STREAM_CALLBACK() macro. If the token + * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled + * and this function has the Callback parameter ommitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param Buffer Pointer to the destination data buffer to write to. + * \param Length Number of bytes to send via the currently selected endpoint. + * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback + * + * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Stream_LE(void* Buffer, uint16_t Length + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + , uint8_t (* const Callback)(void) + #endif + ) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the endpoint from the given buffer in big endian, + * discarding fully read packets from the host as needed. The last packet is not automatically + * discarded once the remaining bytes has been read; the user is responsible for manually + * discarding the last packet from the host via the Endpoint_ClearCurrentBank() macro. Between + * each USB packet, the given stream callback function is executed repeatedly until the endpoint + * is ready to accept the next packet, allowing for early aborts of stream transfers. + * + * The callback routine should be created using the STREAM_CALLBACK() macro. If the token + * NO_STREAM_CALLBACKS is passed via the -D option to the compiler, stream callbacks are disabled + * and this function has the Callback parameter ommitted. + * + * \note This routine should not be used on CONTROL type endpoints. + * + * \param Buffer Pointer to the destination data buffer to write to. + * \param Length Number of bytes to send via the currently selected endpoint. + * \param Callback Name of a callback routine to call between sucessive USB packet transfers, NULL if no callback + * + * \return A value from the Endpoint_Stream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Stream_BE(void* Buffer, uint16_t Length + #if !defined(NO_STREAM_CALLBACKS) || defined(__DOXYGEN__) + , uint8_t (* const Callback)(void) + #endif + ) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in little endian, + * sending full packets to the host as needed. The host OUT acknowedgement is not automatically cleared + * in both failure and success states; the user is responsible for manually clearing the setup OUT to + * finalize the transfer via the Endpoint_ClearSetupOUT() macro. + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param Buffer Pointer to the source data buffer to read from. + * \param Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_Stream_LE(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Writes the given number of bytes to the CONTROL type endpoint from the given buffer in big endian, + * sending full packets to the host as needed. The host OUT acknowedgement is not automatically cleared + * in both failure and success states; the user is responsible for manually clearing the setup OUT to + * finalize the transfer via the Endpoint_ClearSetupOUT() macro. + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param Buffer Pointer to the source data buffer to read from. + * \param Length Number of bytes to read for the currently selected endpoint into the buffer. + * + * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Write_Control_Stream_BE(const void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in little endian, + * discarding fully read packets from the host as needed. The device IN acknowedgement is not + * automatically sent after success or failure states; the user is responsible for manually sending the + * setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro. + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param Buffer Pointer to the destination data buffer to write to. + * \param Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_Stream_LE(void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /** Reads the given number of bytes from the CONTROL endpoint from the given buffer in big endian, + * discarding fully read packets from the host as needed. The device IN acknowedgement is not + * automatically sent after success or failure states; the user is responsible for manually sending the + * setup IN to finalize the transfer via the Endpoint_ClearSetupIN() macro. + * + * \note This routine should only be used on CONTROL type endpoints. + * + * \warning Unlike the standard stream read/write commands, the control stream commands cannot be chained + * together; i.e. the entire stream data must be read or written at the one time. + * + * \param Buffer Pointer to the destination data buffer to write to. + * \param Length Number of bytes to send via the currently selected endpoint. + * + * \return A value from the Endpoint_ControlStream_RW_ErrorCodes_t enum. + */ + uint8_t Endpoint_Read_Control_Stream_BE(void* Buffer, uint16_t Length) ATTR_NON_NULL_PTR_ARG(1); + + /* Function Aliases: */ + /** Alias for Endpoint_Discard_Byte(). + */ + #define Endpoint_Ignore_Byte() Endpoint_Discard_Byte() + + /** Alias for Endpoint_Discard_Word(). + */ + #define Endpoint_Ignore_Word() Endpoint_Discard_Word() + + /** Alias for Endpoint_Discard_DWord(). + */ + #define Endpoint_Ignore_DWord() Endpoint_Discard_DWord() + + /** Alias for Endpoint_Read_Word_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Read_Word() Endpoint_Read_Word_LE() + + /** Alias for Endpoint_Write_Word_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Write_Word(Word) Endpoint_Write_Word_LE(Word) + + /** Alias for Endpoint_Read_DWord_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Read_DWord() Endpoint_Read_DWord_LE() + + /** Alias for Endpoint_Write_DWord_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Write_DWord(DWord) Endpoint_Write_DWord_LE(DWord) + + /** Alias for Endpoint_Read_Stream_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #if !defined(NO_STREAM_CALLBACKS) + #define Endpoint_Read_Stream(Buffer, Length, Callback) Endpoint_Read_Stream_LE(Buffer, Length, Callback) + #else + #define Endpoint_Read_Stream(Buffer, Length) Endpoint_Read_Stream_LE(Buffer, Length) + #endif + + /** Alias for Endpoint_Write_Stream_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #if !defined(NO_STREAM_CALLBACKS) + #define Endpoint_Write_Stream(Buffer, Length, Callback) Endpoint_Write_Stream_LE(Buffer, Length, Callback) + #else + #define Endpoint_Write_Stream(Buffer, Length) Endpoint_Write_Stream_LE(Buffer, Length) + #endif + + /** Alias for Endpoint_Read_Control_Stream_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Read_Control_Stream(Data, Length) Endpoint_Read_Control_Stream_LE(Data, Length) + + /** Alias for Endpoint_Write_Control_Stream_LE(). By default USB transfers use little endian format, thus + * the command with no endianness specifier indicates little endian mode. + */ + #define Endpoint_Write_Control_Stream(Data, Length) Endpoint_Write_Control_Stream_LE(Data, Length) + + /* Private Interface - For use in library only: */ + #if !defined(__DOXYGEN__) + /* Macros: */ + #define Endpoint_AllocateMemory() MACROS{ UECFG1X |= (1 << ALLOC); }MACROE + #define Endpoint_DeallocateMemory() MACROS{ UECFG1X &= ~(1 << ALLOC); }MACROE + + #define _ENDPOINT_GET_MAXSIZE(n) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## n) + #define _ENDPOINT_GET_MAXSIZE2(details) _ENDPOINT_GET_MAXSIZE3(details) + #define _ENDPOINT_GET_MAXSIZE3(maxsize, db) maxsize + + #define _ENDPOINT_GET_DOUBLEBANK(n) _ENDPOINT_GET_DOUBLEBANK2(ENDPOINT_DETAILS_EP ## n) + #define _ENDPOINT_GET_DOUBLEBANK2(details) _ENDPOINT_GET_DOUBLEBANK3(details) + #define _ENDPOINT_GET_DOUBLEBANK3(maxsize, db) db + + #if defined(USB_FULL_CONTROLLER) || defined(USB_MODIFIED_FULL_CONTROLLER) + #define ENDPOINT_DETAILS_EP0 64, true + #define ENDPOINT_DETAILS_EP1 256, true + #define ENDPOINT_DETAILS_EP2 64, true + #define ENDPOINT_DETAILS_EP3 64, true + #define ENDPOINT_DETAILS_EP4 64, true + #define ENDPOINT_DETAILS_EP5 64, true + #define ENDPOINT_DETAILS_EP6 64, true + #else + #define ENDPOINT_DETAILS_EP0 64, true + #define ENDPOINT_DETAILS_EP1 64, false + #define ENDPOINT_DETAILS_EP2 64, false + #define ENDPOINT_DETAILS_EP3 64, true + #define ENDPOINT_DETAILS_EP4 64, true + #endif + + #if defined(STATIC_ENDPOINT_CONFIGURATION) + #define Endpoint_ConfigureEndpoint(Number, Type, Direction, Size, Banks) \ + Endpoint_ConfigureEndpointStatic(Number, \ + ((Type << EPTYPE0) | Direction), \ + ((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size))); + #endif + + /* Function Prototypes: */ + void Endpoint_ClearEndpoints(void); + bool Endpoint_ConfigureEndpointStatic(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_ALWAYSINLINE; + static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) + { + if (Bytes <= 8) + return (0 << EPSIZE0); + else if (Bytes <= 16) + return (1 << EPSIZE0); + else if (Bytes <= 32) + return (2 << EPSIZE0); + #if defined(USB_LIMITED_CONTROLLER) + else + return (3 << EPSIZE0); + #else + else if (Bytes <= 64) + return (3 << EPSIZE0); + else if (Bytes <= 128) + return (4 << EPSIZE0); + else + return (5 << EPSIZE0); + #endif + }; + + #endif + + /* Disable C linkage for C++ Compilers: */ + #if defined(__cplusplus) + } + #endif + +#endif -- cgit v1.2.3