aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h1094
1 files changed, 1094 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h
new file mode 100644
index 0000000..672ab28
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/usbd/app_usbd_class_base.h
@@ -0,0 +1,1094 @@
+/**
+ * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef APP_USBD_CLASS_BASE_H__
+#define APP_USBD_CLASS_BASE_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "app_usbd_types.h"
+#include "nrf_drv_usbd.h"
+#include "nrf_assert.h"
+#include "app_util.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup app_usbd_class_base USBD Class Base module
+ * @ingroup app_usbd
+ *
+ * @brief @tagAPI52840 The base for any class instance is defined in this module.
+ *
+ * @details Any class instance must start from base class instance structure.
+ * This makes them compatible with USBD library independently of the
+ * implementation details.
+ * @{
+ */
+
+/**
+ * @brief Endpoint configuration
+ */
+typedef struct
+{
+ nrf_drv_usbd_ep_t address; //!< Endpoint address
+} app_usbd_class_ep_conf_t;
+
+/**
+ * @brief Interface configuration
+ */
+typedef struct
+{
+ uint8_t number; //!< Interface number
+ uint8_t ep_cnt; //!< Endpoint number
+ uint8_t ep_offset; //!< Offset of the first endpoint
+ /**< Offset in bytes of the first endpoint.
+ * The offset is calculated from the address of this interface structure
+ */
+} app_usbd_class_iface_conf_t;
+
+/**
+ * @brief Instance variable data
+ */
+typedef struct
+{
+ app_usbd_class_inst_t const * p_next; //!< Pointer to the next instance
+ app_usbd_class_inst_t const * p_sof_next; //!< Pointer to the next SOF event requiring instance
+} app_usbd_class_data_t;
+
+/**
+ * @brief Class descriptor context
+ */
+typedef struct
+{
+ uint32_t line; //!< Number of line to resume writing descriptors from
+ uint8_t data_buffer; //!< Data from last call of feeder
+} app_usbd_class_descriptor_ctx_t;
+
+/**
+ * @brief Class descriptor state
+ */
+typedef struct
+{
+ uint8_t * p_buffer; //!< Pointer to buffer
+ uint32_t current_size; //!< Current size of descriptor
+ uint32_t maximum_size; //!< Maximum size of descriptor
+ app_usbd_class_descriptor_ctx_t * p_context; //!< Pointer to context
+} app_usbd_class_descriptor_state_t;
+
+/**
+ * @brief Class interface function set
+ * */
+typedef struct {
+ /**
+ * @brief Instance callback function
+ *
+ * The function used by every class instance.
+ * @param[in,out] p_inst Instance of the class
+ * @param[in] p_event Event to process
+ *
+ * @return Standard error code
+ *
+ * @note If given event is not supported by class, return @ref NRF_ERROR_NOT_SUPPORTED
+ */
+ ret_code_t (* event_handler)(app_usbd_class_inst_t const * const p_inst,
+ app_usbd_complex_evt_t const * const p_event);
+
+ /**
+ * @brief Instance feed descriptors
+ *
+ * Feeds whole descriptor of the instance
+ * @param[in] p_ctx Class descriptor context
+ * @param[in,out] p_inst Instance of the class
+ * @param[out] p_buff Buffer for descriptor
+ * @param[in] max_size Requested size of the descriptor
+ *
+ * @return True if not finished feeding the descriptor, false if done
+ */
+ bool (* feed_descriptors)(app_usbd_class_descriptor_ctx_t * p_ctx,
+ app_usbd_class_inst_t const * p_inst,
+ uint8_t * p_buff,
+ size_t max_size);
+
+
+ /**
+ * @brief Select interface
+ *
+ * Function called when class interface has to be selected.
+ *
+ * This function would be called for every interface when:
+ * - SET_INTERFACE command is processed by the default handler
+ * - SET_CONFIG(1) command is processed by the default handler
+ *
+ * @note Remember to disable all the endpoints that are not used
+ * in the selected configuration.
+ * @note If this function pointer is NULL default procedure would
+ * just enable all the interface endpoints and selecting
+ * alternate configurations other than 0 would generate error.
+ * @note Calling the function with alternate setting 0 has to always succeed.
+ *
+ * @param[in,out] p_inst Instance of the class
+ * @param[in] iface_idx Index of the interface inside class structure
+ * @param[in] alternate Alternate setting that should be selected
+ *
+ * @return Function has to return @ref NRF_SUCCESS when it has successfully proceed
+ * interface selection.
+ * If it returns @ref NRF_ERROR_NOT_SUPPORTED, default function would be used
+ * to proceed the request - just like there would be NULL pointer in this field.
+ * Any other kind of error would make library to STALL the request.
+ */
+ ret_code_t (* iface_select)(app_usbd_class_inst_t const * const p_inst,
+ uint8_t iface_idx,
+ uint8_t alternate);
+
+ /**
+ * @brief Deselect interface
+ *
+ * Function called when the class interface has to be deselected.
+ *
+ * This function would be called for every interface when:
+ * - Library start internal event is processed by the default handler
+ * - RESET event is processed by the default handler
+ * - SET_ADDRESS is processed by the default handler
+ * - SET_CONFIG(0) is processed by the default handler
+ *
+ * @note Just after this function is called all the interface
+ * endpoints would be disabled.
+ * This function does not has to take care about it.
+ * @note If this function pointer is NULL default procedure would
+ * just disable all the interface endpoints.
+ *
+ * @param[in,out] p_inst Instance of the class
+ * @param[in] iface_idx Index of the interface inside class structure
+ */
+ void (* iface_deselect)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx);
+
+ /**
+ * @brief Get current interface
+ *
+ * Function called when class interface has to return its alternate settings
+ * in reaction on GET_INTERFACE command.
+ * It should be defined in a pair with @ref app_usbd_class_methods_t::iface_select.
+ *
+ * @param[in] p_inst Instance of the class
+ * @param[in] iface_idx Index of the interface inside class structure
+ *
+ * @return Current alternate setting of the selected interface.
+ *
+ * @note For the classes that support this function, when an interface that has not alternate
+ * configurations has been selected this function has to return 0 - default alternate setting.
+ *
+ * @note If this function pointer it NULL default procedure would return alternate interface
+ * value 0.
+ */
+ uint8_t (* iface_selection_get)(app_usbd_class_inst_t const * const p_inst, uint8_t iface_idx);
+
+} app_usbd_class_methods_t;
+
+/**
+ * @brief The instance structure itself
+ *
+ * The structure of base class instance
+ */
+struct app_usbd_class_inst_s
+{
+ app_usbd_class_data_t * p_data; //!< Pointer to non-constant data
+ app_usbd_class_methods_t const * p_class_methods; //!< Class interface methods
+ struct
+ {
+ uint8_t cnt; //!< Number of defined interfaces
+ uint8_t config[]; //!< Interface configuration data followed by endpoint data
+ } iface; //!< Interface structure
+};
+
+
+/**
+ * @brief Get total number of interfaces
+ *
+ *
+ */
+static inline uint8_t app_usbd_class_iface_count_get(app_usbd_class_inst_t const * const p_inst)
+{
+ return p_inst->iface.cnt;
+}
+
+/**
+ * @brief Interface accessing function
+ *
+ * Get interface pointer.
+ * Interfaces creates continuous array in the memory so it is possible to get
+ * interface with index 0 and the just iterate to the next one.
+ *
+ * @param p_inst Pointer to the class instance
+ * @param iface_idx Index of the instance to get.
+ * This is not the interface identifier.
+ * Technically it is the index of the interface in the class description array.
+ * @return Pointer to the interface configuration parameters or NULL if given index is out of interface scope for given class.
+ */
+static inline app_usbd_class_iface_conf_t const * app_usbd_class_iface_get(
+ app_usbd_class_inst_t const * const p_inst,
+ uint8_t iface_idx)
+{
+ ASSERT(NULL != p_inst);
+ if (iface_idx >= (app_usbd_class_iface_count_get(p_inst)))
+ {
+ return NULL;
+ }
+
+ app_usbd_class_iface_conf_t const * p_interface =
+ (app_usbd_class_iface_conf_t const * )(p_inst->iface.config);
+ return &(p_interface[iface_idx]);
+}
+
+/**
+ * @brief Get interface number
+ *
+ * @param p_iface Pointer to interface structure
+ *
+ * @return Interface number from interface configuration structure
+ */
+static inline uint8_t app_usbd_class_iface_number_get(
+ app_usbd_class_iface_conf_t const * const p_iface)
+{
+ return p_iface->number;
+}
+
+/**
+ * @brief Get number of endpoints in interface
+ *
+ * @param p_iface Pointer to interface structure
+ *
+ * @return Number of endpoints used by given interface
+ */
+static inline uint8_t app_usbd_class_iface_ep_count_get(
+ app_usbd_class_iface_conf_t const * const p_iface)
+{
+ return p_iface->ep_cnt;
+}
+
+/**
+ * @brief Interface Endpoint accessing function
+ *
+ * @param p_iface Interface configuration pointer
+ * @param ep_idx Endpoint index
+ *
+ * @return Endpoint information structure pointer or NULL if given index is outside of endpoints for selected interface.
+ *
+ * @sa app_usbd_class_iface_get
+ */
+static inline app_usbd_class_ep_conf_t const * app_usbd_class_iface_ep_get(
+ app_usbd_class_iface_conf_t const * const p_iface,
+ uint8_t ep_idx)
+{
+ ASSERT(NULL != p_iface);
+ if (ep_idx >= p_iface->ep_cnt)
+ {
+ return NULL;
+ }
+
+ app_usbd_class_ep_conf_t const * p_ep =
+ (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset);
+ return &(p_ep[ep_idx]);
+}
+
+/**
+ * @brief Translate endpoint address to class index
+ *
+ * @param p_iface Interface configuration pointer
+ * @param ep_address Endpoint address
+ *
+ * @return Endpoint index or number of endpoints if not found
+ *
+ */
+static inline uint8_t app_usbd_class_iface_ep_idx_get(
+ app_usbd_class_iface_conf_t const * const p_iface,
+ nrf_drv_usbd_ep_t ep_address)
+{
+ ASSERT(NULL != p_iface);
+ app_usbd_class_ep_conf_t const * p_ep =
+ (app_usbd_class_ep_conf_t const * )(((uint8_t const *)p_iface) + p_iface->ep_offset);
+
+ uint8_t i;
+ for (i = 0; i < p_iface->ep_cnt; ++i)
+ {
+ if (ep_address == p_ep[i].address)
+ {
+ break;
+ }
+ }
+
+ return i;
+}
+
+/**
+ * @brief Get the selected endpoint address
+ *
+ * @param p_ep Endpoint configuration structure
+ *
+ * @return Endpoint address
+ */
+static inline nrf_drv_usbd_ep_t app_usbd_class_ep_address_get(app_usbd_class_ep_conf_t const * p_ep)
+{
+ return (nrf_drv_usbd_ep_t)p_ep->address;
+}
+
+/**
+ * @brief Get the pointer to the writable instance data
+ *
+ * @param p_inst Instance pointer
+ * @return Pointer to writable instance data
+ */
+static inline app_usbd_class_data_t * app_usbd_class_data_access(
+ app_usbd_class_inst_t const * const p_inst)
+{
+ return p_inst->p_data;
+}
+
+/**
+ * @name Internal macros for argument mapping
+ *
+ * Functions to be used as a mapping macro for @ref MACRO_MAP, @ref MACRO_MAP_FOR or @ref MACRO_MAP_FOR_PARAM
+ * @{
+ */
+ /**
+ * @brief Count the number of endpoints in given configuration
+ *
+ * Config should be given as a interface configuration in a brackets:
+ * @code
+ * (interface_nr, ep1, ep2, ep3)
+ * @endcode
+ * Number of endpoints may vary from 0 to a few (technically up to 16, but it seems not to make sense to use more than 4).
+ * Interface number is always present.
+ *
+ * @param iface_config Single interface configuration (in brackets)
+ *
+ * @return Number of endpoints in interface. This is computed value - can be used by compiler but not by preprocessor.
+ */
+ #define APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config) \
+ (NUM_VA_ARGS(BRACKET_EXTRACT(iface_config)) - 1)
+
+ /**
+ * @brief Adds the number of endpoints in given config to the current value
+ *
+ * This is basically @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_ with plus sign added.
+ *
+ * @param iface_config See parameters documentation in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_
+ *
+ * @return Plus sign followed by number of endpoints in interface.
+ *
+ * @sa APP_USBD_CLASS_CONF_IFACE_EP_COUNT_
+ */
+ #define APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_(iface_config) \
+ + APP_USBD_CLASS_CONF_IFACE_EP_COUNT_(iface_config)
+
+ /**
+ * @brief Create variable for endpoint
+ */
+
+ /**
+ * @brief Extract endpoints given interface configuration
+ *
+ * This macro gets single endpoint configuration and extracts all the endpoints.
+ * It also adds comma on the end of extracted endpoints.
+ * This way when this macro is called few times it generates nice list of all endpoints
+ * that may be used to array initialization.
+ *
+ * @param iface_config Single interface configuration in brackets.
+ * The format should be similar like described in @ref APP_USBD_CLASS_CONF_IFACE_EP_COUNT_.
+ */
+ #define APP_USBD_CLASS_IFACE_EP_EXTRACT_(iface_config) \
+ CONCAT_2(APP_USBD_CLASS_IFACE_EP_EXTRACT_, \
+ NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \
+ (BRACKET_EXTRACT(iface_config))
+
+ /**
+ * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_
+ *
+ * This macro is called when interface has no endpoints
+ */
+ #define APP_USBD_CLASS_IFACE_EP_EXTRACT_0(iface_nr)
+
+ /**
+ * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_EP_EXTRACT_
+ *
+ * This macro is called when interface has at least one endpoint
+ */
+ #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1(...) \
+ APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(__VA_ARGS__)
+
+ #define APP_USBD_CLASS_IFACE_EP_EXTRACT_1_(iface_nr, ...) \
+ MACRO_MAP_REC(PARAM_CBRACE, __VA_ARGS__)
+
+ /**
+ * @brief Generate configuration for single interface
+ *
+ * This macro extract configuration for single interface.
+ * The configuration is inside curly brackets and comma is added on the end.
+ * This mean it can be directly used to init array of interface configurations.
+ *
+ * @param iface_config Single interface configuration
+ * @param N Currently processed configuration
+ * @param iface_configs All interfaces configuration in brackets
+ */
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_(iface_config, N, iface_configs) \
+ CONCAT_2(APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \
+ NUM_VA_ARGS_IS_MORE_THAN_1(BRACKET_EXTRACT(iface_config))) \
+ (N, iface_configs, BRACKET_EXTRACT(iface_config))
+
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_x(iface_config, N, iface_configs) \
+ [N] = !!!iface_config!!!
+ /**
+ * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_
+ *
+ * This macro is called when interface has no endpoints
+ */
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0(N, iface_configs, iface_nr) \
+ APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr)
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_0_(N, iface_configs, iface_nr) \
+ { .number = iface_nr, .ep_cnt = 0, .ep_offset = 0 },
+
+ /**
+ * @brief Auxiliary macro for @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_
+ *
+ * This macro is called when interface has at last one endpoint
+ */
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1(N, iface_configs, ...) \
+ APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, __VA_ARGS__)
+ #define APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_1_(N, iface_configs, iface_nr, ...) \
+ { .number = iface_nr, .ep_cnt = NUM_VA_ARGS(__VA_ARGS__), \
+ .ep_offset = APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) * \
+ sizeof(app_usbd_class_ep_conf_t) \
+ + ((NUM_VA_ARGS(BRACKET_EXTRACT(iface_configs)) - N) * \
+ sizeof(app_usbd_class_iface_conf_t)) \
+ },
+
+/** @} */
+
+
+/**
+ * @name Macros that uses mapping macros internally
+ *
+ * Auxiliary macros that uses mapping macros to make some calculations or realize other functionality.
+ * Mapped here for easier unit testing and to hide complex mapping functions calling.
+ * @{
+ */
+
+/**
+ * @brief Count total number of endpoints
+ *
+ * @param iface_configs List of interface configurations like explained
+ * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF
+ *
+ * @return The equation to calculate the number of endpoints by compiler.
+ */
+#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(iface_configs) \
+ (0 MACRO_MAP(APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs)))
+
+/**
+ * @brief Count total number of endpoint up-to interface index
+ *
+ * The version of @ref APP_USBD_CLASS_CONF_TOTAL_EP_COUNT macro which takes the
+ * number of interfaces to analyze.
+ *
+ * @param N Number of interfaces to analyze
+ * @param iface_configs List of interface configurations like explained
+ * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF
+ *
+ * @return The equation to calculate the number of endpoints by compiler.
+ */
+#define APP_USBD_CLASS_CONF_TOTAL_EP_COUNT_N(N, iface_configs) \
+ (0 MACRO_MAP_N(N, APP_USBD_CLASS_CONF_IFACE_EP_PLUS_COUNT_, BRACKET_EXTRACT(iface_configs)))
+
+/**
+ * @brief Extract configurations for interfaces
+ *
+ * This macro extracts the configurations for every interface.
+ * Basically uses the @ref APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_ macro on every
+ * configuration found.
+ *
+ * This should generate interface configuration initialization data
+ * in comma separated initializers in curly braces.
+ *
+ * @param iface_configs List of interface configurations like explained
+ * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF
+ *
+ * @return Comma separated initialization data for all interfaces.
+ */
+/*lint -emacro( (40), APP_USBD_CLASS_IFACES_CONFIG_EXTRACT) */
+#define APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(iface_configs) \
+ MACRO_MAP_FOR_PARAM(iface_configs, \
+ APP_USBD_CLASS_IFACE_CONFIG_EXTRACT_, \
+ BRACKET_EXTRACT(iface_configs))
+
+/**
+ * @brief Extract all endpoints
+ *
+ * Macro that extracts all endpoints from every interface
+ *
+ * @param iface_configs List of interface configurations like explained
+ * in documentation for @ref APP_USBD_CLASS_INSTANCE_TYPEDEF
+ *
+ * @return Comma separated list of endpoints
+ */
+/*lint -emacro( (40), APP_USBD_CLASS_IFACES_EP_EXTRACT) */
+#define APP_USBD_CLASS_IFACES_EP_EXTRACT(iface_configs) \
+ MACRO_MAP(APP_USBD_CLASS_IFACE_EP_EXTRACT_, BRACKET_EXTRACT(iface_configs))
+
+
+/** @} */
+
+
+/**
+ * @brief USBD instance of class mnemonic
+ *
+ * Macro that generates mnemonic for the name of the structure that describes instance for selected class.
+ *
+ * @param type_name The name of the instance without _t postfix
+ *
+ * @return The name with the right postfix to create the name for the type for the class.
+ */
+#define APP_USBD_CLASS_INSTANCE_TYPE(type_name) CONCAT_2(type_name, _t)
+
+/**
+ * @brief USBD data for instance class mnemonic
+ *
+ * The mnemonic of the variable type that holds writable part of the class instance.
+ *
+ * @param type_name The name of the instance without _t postfix
+ *
+ * @return The name with the right postfix to create the name for the data type for the class.
+ */
+#define APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(type_name, _data_t)
+
+/**
+ * @brief Declare class specific member of class instance
+ *
+ * @param type Type of the attached class configuration.
+ *
+ * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF
+ */
+#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type) type class_part;
+
+/**
+ * @brief Used if there is no class specific configuration
+ *
+ * This constant can be used if there is no specific configuration inside created instance
+ *
+ * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF
+ */
+#define APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE
+
+/**
+ * @brief Declare class specific member of class data
+ *
+ * @param type Type of the attached class data.
+ *
+ * @sa APP_USBD_CLASS_DATA_TYPEDEF
+ */
+#define APP_USBD_CLASS_DATA_SPECIFIC_DEC(type) APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC(type)
+
+/**
+ * @brief Used if there is no class specific data
+ *
+ * This constant can be used if there is no specific writable data inside created instance
+ *
+ * @sa APP_USBD_CLASS_DATA_TYPEDEF
+ */
+#define APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE
+
+
+
+
+/**
+ * @brief Instance structure declaration
+ *
+ * The macro that declares a variable type that would be used to store given class instance.
+ * Class instance stores all the data from @ref app_usbd_class_inst_t and overlaid data for specified class.
+ *
+ * The structure of interface configuration data:
+ * @code
+ * (
+ * (iface1_nr, (ep1, ep2, ep3)),
+ (iface2_nr),
+ (iface3_nr, (ep4))
+ * )
+ * @endcode
+ *
+ * @param type_name The name of the instance without _t postfix.
+ * @param interfaces_configs List of interface configurations like explained above.
+ * @param class_config_dec Result of the macro
+ * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or
+ * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE
+ *
+ * @return The definition of the structure type that holds all the required data.
+ *
+ * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead.
+ *
+ * @note APP_USBD_CLASS_DATA_TYPEDEF has to be called first for the compilation to success.
+ *
+ * @sa APP_USBD_CLASS_TYPEDEF
+ */
+#define APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interfaces_configs, class_config_dec) \
+ typedef union CONCAT_2(type_name, _u) \
+ { \
+ app_usbd_class_inst_t base; \
+ struct \
+ { \
+ APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \
+ app_usbd_class_methods_t const * p_class_methods; \
+ struct \
+ { \
+ uint8_t cnt; \
+ app_usbd_class_iface_conf_t \
+ config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \
+ app_usbd_class_ep_conf_t \
+ ep[APP_USBD_CLASS_CONF_TOTAL_EP_COUNT(interfaces_configs)]; \
+ } iface; \
+ class_config_dec \
+ } specific; \
+ } APP_USBD_CLASS_INSTANCE_TYPE(type_name)
+
+/**
+ * @brief Same as @ref APP_USBD_CLASS_INSTANCE_TYPEDEF but for class with EP0 only.
+ */
+#define APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interfaces_configs, class_config_dec) \
+ typedef union CONCAT_2(type_name, _u) \
+ { \
+ app_usbd_class_inst_t base; \
+ struct \
+ { \
+ APP_USBD_CLASS_DATA_TYPE(type_name) * p_data; \
+ app_usbd_class_methods_t const * p_class_methods; \
+ struct \
+ { \
+ uint8_t cnt; \
+ app_usbd_class_iface_conf_t \
+ config[NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs))]; \
+ } iface; \
+ class_config_dec \
+ } specific; \
+ } APP_USBD_CLASS_INSTANCE_TYPE(type_name)
+
+/**
+ * @brief Writable data structure declaration
+ *
+ * The macro that declares a variable type that would be used to store given class writable data.
+ * Writable data contains base part of the type @ref app_usbd_class_data_t followed by
+ * class specific data.
+ *
+ * @param type_name The name of the type without _t postfix.
+ * @param class_data_dec Result of the macro
+ * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or
+ * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE
+ *
+ * @return The definition of the structure type that holds all the required writable data
+ *
+ * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_DATA_TYPEDEF instead.
+ *
+ * @sa APP_USBD_CLASS_TYPEDEF
+ */
+#define APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec) \
+ typedef struct \
+ { \
+ app_usbd_class_data_t base; \
+ class_data_dec \
+ }APP_USBD_CLASS_DATA_TYPE(type_name)
+
+
+/**
+ * @brief Declare all data types required by the class instance
+ *
+ * Macro that declares data type first and then instance type.
+ *
+ * @param type_name The name of the type without _t postfix.
+ * @param interface_configs List of interface configurations like in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF.
+ * @param class_config_dec Result of the macro
+ * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC or
+ * @ref APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE
+ * @param class_data_dec Result of the macro
+ * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC or
+ * @ref APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE
+ *
+ * @return Declaration of the data type for the instance and instance itself.
+ *
+ * @sa APP_USBD_CLASS_DATA_TYPEDEF
+ * @sa APP_USBD_CLASS_INSTANCE_TYPEDEF
+ */
+#define APP_USBD_CLASS_TYPEDEF(type_name, interface_configs, class_config_dec, class_data_dec) \
+ APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \
+ APP_USBD_CLASS_INSTANCE_TYPEDEF(type_name, interface_configs, class_config_dec)
+
+/**
+ * @brief Same as @ref APP_USBD_CLASS_TYPEDEF but for class with EP0 only.
+ */
+#define APP_USBD_CLASS_NO_EP_TYPEDEF(type_name, \
+ interface_configs, \
+ class_config_dec, \
+ class_data_dec) \
+ APP_USBD_CLASS_DATA_TYPEDEF(type_name, class_data_dec); \
+ APP_USBD_CLASS_INSTANCE_NO_EP_TYPEDEF(type_name, interface_configs, class_config_dec)
+
+/**
+ * @brief Forward declaration of type defined by @ref APP_USBD_CLASS_TYPEDEF
+ *
+ * @param type_name The name of the type without _t postfix.
+ * */
+#define APP_USBD_CLASS_FORWARD(type_name) union CONCAT_2(type_name, _u)
+
+/**
+ * @brief Generate the initialization data for
+ *
+ * Macro that generates the initialization data for instance.
+ *
+ * @param p_ram_data Pointer to writable instance data structure
+ * @param class_methods Class methods
+ * @param interfaces_configs Exactly the same interface config data that in @ref APP_USBD_CLASS_INSTANCE_TYPEDEF
+ * @param class_config_part Configuration part. The data should be inside brackets.
+ * Any data here would be removed from brackets and then put as an initialization
+ * data for class_part member of instance structure.
+ *
+ * @note It should not be used directly in the final application. See @ref APP_USBD_CLASS_INST_DEF instead.
+ */
+#define APP_USBD_CLASS_INSTANCE_INITVAL(p_ram_data, \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part) \
+ { \
+ .specific = { \
+ .p_data = p_ram_data, \
+ .p_class_methods = class_methods, \
+ .iface = { \
+ .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \
+ .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) }, \
+ .ep = { APP_USBD_CLASS_IFACES_EP_EXTRACT(interfaces_configs) } \
+ }, \
+ BRACKET_EXTRACT(class_config_part) \
+ } \
+ }
+
+/**
+ * @brief Same as @ref APP_USBD_CLASS_INSTANCE_INITVAL but for class with EP0 only.
+ */
+#define APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL(p_ram_data, \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part) \
+ { \
+ .specific = { \
+ .p_data = p_ram_data, \
+ .p_class_methods = class_methods, \
+ .iface = { \
+ .cnt = NUM_VA_ARGS(BRACKET_EXTRACT(interfaces_configs)), \
+ .config = { APP_USBD_CLASS_IFACES_CONFIG_EXTRACT(interfaces_configs) } \
+ }, \
+ BRACKET_EXTRACT(class_config_part) \
+ } \
+ }
+
+/**
+ * @brief Define the base class instance
+ *
+ * Macro that defines whole instance variable and fill it with initialization data.
+ *
+ * The tricky part is @c class_config_part.
+ * The configuration data here has to be placed inside brackets.
+ * Then any type of values can be used depending on the type used in @ref APP_USBD_CLASS_TYPEDEF.
+ * If instance does not has any specyfic data, use just empty bracket here.
+ * @code
+ * APP_USBD_CLASS_TYPEDEF(
+ * some_base_class,
+ * CLASS_BASE_CONFIGURATION,
+ * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE,
+ * APP_USBD_CLASS_DATA_SPECIFIC_DEC_NONE
+ * );
+ * APP_USBD_CLASS_INST_DEF(
+ * some_base_class_inst,
+ * some_base_class,
+ * base_class_event_handler,
+ * CLASS_BASE_CONFIGURATION,
+ * () // Empty configuration
+ * );
+ * @endcode
+ *
+ * If the type of instance configuration is simple type, just provide initialization value:
+ * @code
+ * APP_USBD_CLASS_TYPEDEF(
+ * some_base_class,
+ * CLASS_BASE_CONFIGURATION,
+ * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE,
+ * APP_USBD_CLASS_DATA_SPECIFIC_DEC(uint8_t)
+ * );
+ * APP_USBD_CLASS_INST_DEF(
+ * some_base_class_inst,
+ * some_base_class,
+ * base_class_event_handler,
+ * CLASS_BASE_CONFIGURATION,
+ * (12) // Example values
+ * );
+ * @endcode
+ *
+ * If the type of instance configuration is structure, provide initialization value for the whole structure:
+ * @code
+ * typedef structure
+ * {
+ * uint32_t p1;
+ * uint8_t p2;
+ * }my_config_t;
+ *
+ * APP_USBD_CLASS_TYPEDEF(
+ * some_base_class,
+ * CLASS_BASE_CONFIGURATION,
+ * APP_USBD_CLASS_INSTANCE_SPECIFIC_DEC_NONE,
+ * APP_USBD_CLASS_DATA_SPECIFIC_DEC(my_config_t)
+ * );
+ * APP_USBD_CLASS_INST_DEF(
+ * some_base_class_inst,
+ * some_base_class,
+ * base_class_event_handler,
+ * CLASS_BASE_CONFIGURATION,
+ * ({12, 3}) // Example values
+ * );
+ * @endcode
+ *
+ * @param instance_name The name of created instance variable.
+ * It would be constant variable and its type would be app_usbd_class_inst_t.
+ * @param type_name The name of the variable type. It has to be the same type that was passed to
+ * @ref APP_USBD_CLASS_TYPEDEF
+ * @param class_methods Class unified interface.
+ * @param interfaces_configs The same configuration data that the one passed to @ref APP_USBD_CLASS_TYPEDEF
+ * @param class_config_part Configuration data to the type that was declared by class_data_dec when calling
+ * @ref APP_USBD_CLASS_TYPEDEF.
+ * Configuration data has to be provided in brackets.
+ * It would be extracted from brackets and placed in initialization part of configuration structure.
+ * See detailed description of this macro for more informations.
+ */
+#define APP_USBD_CLASS_INST_DEF(instance_name, \
+ type_name, \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part) \
+ static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \
+ static const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \
+ APP_USBD_CLASS_INSTANCE_INITVAL( \
+ &CONCAT_2(instance_name, _data), \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part)
+
+
+/**
+ * @brief Define the base class instance in global scope
+ *
+ * This is the same macro like @ref APP_USBD_CLASS_INST_DEF but it creates the instance
+ * without static keyword.
+ *
+ * @param instance_name See documentation for @ref APP_USBD_CLASS_INST_DEF
+ * @param type_name See documentation for @ref APP_USBD_CLASS_INST_DEF
+ * @param class_methods See documentation for @ref APP_USBD_CLASS_INST_DEF
+ * @param interfaces_configs See documentation for @ref APP_USBD_CLASS_INST_DEF
+ * @param class_config_part See documentation for @ref APP_USBD_CLASS_INST_DEF
+ */
+#define APP_USBD_CLASS_INST_GLOBAL_DEF(instance_name, \
+ type_name, \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part) \
+ static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \
+ const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \
+ APP_USBD_CLASS_INSTANCE_INITVAL( \
+ &CONCAT_2(instance_name, _data), \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part)
+
+/**
+ * @brief Same as @ref APP_USBD_CLASS_INST_GLOBAL_DEF but for class with EP0 only.
+ */
+#define APP_USBD_CLASS_INST_NO_EP_GLOBAL_DEF(instance_name, \
+ type_name, \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part) \
+ static APP_USBD_CLASS_DATA_TYPE(type_name) CONCAT_2(instance_name, _data); \
+ const APP_USBD_CLASS_INSTANCE_TYPE(type_name) instance_name = \
+ APP_USBD_CLASS_INSTANCE_NO_EP_INITVAL( \
+ &CONCAT_2(instance_name, _data), \
+ class_methods, \
+ interfaces_configs, \
+ class_config_part)
+/**
+ * @brief Access class specific configuration
+ *
+ * Macro that returns class specific configuration.
+ *
+ * @param[in] p_inst Instance pointer
+ *
+ * @return A pointer for class specific part of the instance
+ *
+ * @note If macro is used on the instance that has no class specific configuration
+ * an error would be generated during compilation.
+ */
+#define APP_USBD_CLASS_GET_SPECIFIC_CONFIG(p_inst) (&((p_inst)->specific.class_part))
+
+/**
+ * @brief Access class specific data
+ *
+ * @param[in] p_inst Instance pointer
+ *
+ * @return A pointer for class specific part of writable data
+ *
+ * @note If macro is used on the instance that has no class specific data
+ * an error would be generated during compilation.
+ */
+#define APP_USBD_CLASS_GET_SPECIFIC_DATA(p_inst) (&(((p_inst)->specific.p_data)->class_part))
+
+/**
+ * @brief Macro to get base instance from class specific instance
+ *
+ * This macro may be used on class specific instance to get base instance that
+ * can be processed by base instance access functions.
+ * Class specific instance can be just casted to class base instance,
+ * but then we would totally lost type safety.
+ *
+ * A little more safe is to use pointer to base member of class instance.
+ * This would generate an error when used on any variable that has no base member
+ * and would generate also error if this base member is wrong type.
+ */
+#define APP_USBD_CLASS_BASE_INSTANCE(p_inst) (&((p_inst)->base))
+
+/*lint -emacro(142 438 616 646, APP_USBD_CLASS_DESCRIPTOR_INIT, APP_USBD_CLASS_DESCRIPTOR_BEGIN, APP_USBD_CLASS_DESCRIPTOR_YIELD, APP_USBD_CLASS_DESCRIPTOR_END, APP_USBD_CLASS_DESCRIPTOR_WRITE)*/
+
+/**
+ * @brief Initialize class descriptor
+ *
+ * @param[in] p_ctx Class descriptor context
+ */
+
+#define APP_USBD_CLASS_DESCRIPTOR_INIT(p_ctx) \
+ (p_ctx)->line = 0;
+
+/**
+ * @brief Begin class descriptor
+ *
+ * @param[in] p_ctx Class descriptor context
+ * @param[in] p_buff Buffer to write into
+ * @param[in] max_size Size of the buffer
+ */
+
+#define APP_USBD_CLASS_DESCRIPTOR_BEGIN(p_ctx, p_buff, max_size) \
+ ASSERT((p_ctx) != NULL); \
+ app_usbd_class_descriptor_state_t this_descriptor_feed; \
+ this_descriptor_feed.p_buffer = (p_buff); \
+ this_descriptor_feed.current_size = 0; \
+ this_descriptor_feed.maximum_size = (max_size); \
+ this_descriptor_feed.p_context = (p_ctx); \
+ switch ((this_descriptor_feed.p_context)->line) \
+ { \
+ case 0: \
+ ;
+
+/**
+ * @brief Yield class descriptor
+ *
+ */
+
+#define APP_USBD_CLASS_DESCRIPTOR_YIELD() \
+do \
+{ \
+ (this_descriptor_feed.p_context)->line = __LINE__; \
+ return true; \
+ case __LINE__: \
+ ; \
+} while (0)
+
+/*lint -emacro(438 527, APP_USBD_CLASS_DESCRIPTOR_END)*/
+
+/**
+ * @brief End class descriptor
+ *
+ * This function has to be called at the end of class descriptor feeder function.
+ * No other operations in feeder function can be done after calling it.
+ */
+
+#define APP_USBD_CLASS_DESCRIPTOR_END() \
+ APP_USBD_CLASS_DESCRIPTOR_YIELD(); \
+ } \
+ (this_descriptor_feed.p_context)->line = 0; \
+ return false;
+
+
+/**
+ * @brief Write descriptor using protothreads
+ *
+ * This function writes one byte to the buffer with offset. If buffer is full
+ * it yields.
+ *
+ * It is used by the class descriptor feeders internally.
+ *
+ * @ref APP_USBD_CLASS_DESCRIPTOR_BEGIN has to be called before using this function.
+ * @ref APP_USBD_CLASS_DESCRIPTOR_END has to be called after last use of this function.
+ *
+ * @param data Byte to be written to buffer
+ */
+#define APP_USBD_CLASS_DESCRIPTOR_WRITE(data) \
+do \
+{ \
+ (this_descriptor_feed.p_context)->data_buffer = (data); \
+ if (this_descriptor_feed.current_size >= this_descriptor_feed.maximum_size) \
+ { \
+ APP_USBD_CLASS_DESCRIPTOR_YIELD(); \
+ } \
+ if(this_descriptor_feed.p_buffer != NULL) \
+ { \
+ *(this_descriptor_feed.p_buffer + this_descriptor_feed.current_size) = \
+ (this_descriptor_feed.p_context)->data_buffer; \
+ } \
+ this_descriptor_feed.current_size++; \
+} while(0);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APP_USBD_CLASS_BASE_H__ */