| /* |
| * Copyright (c) 2018 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ |
| #define ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ |
| |
| #include <logging/log_msg.h> |
| #include <logging/log_msg2.h> |
| #include <stdarg.h> |
| #include <sys/__assert.h> |
| #include <sys/util.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * @brief Logger backend interface |
| * @defgroup log_backend Logger backend interface |
| * @ingroup logger |
| * @{ |
| */ |
| |
| /* Forward declaration of the log_backend type. */ |
| struct log_backend; |
| |
| /** |
| * @brief Logger backend API. |
| */ |
| struct log_backend_api { |
| void (*process)(const struct log_backend *const backend, |
| union log_msg2_generic *msg); |
| |
| void (*put)(const struct log_backend *const backend, |
| struct log_msg *msg); |
| void (*put_sync_string)(const struct log_backend *const backend, |
| struct log_msg_ids src_level, uint32_t timestamp, |
| const char *fmt, va_list ap); |
| void (*put_sync_hexdump)(const struct log_backend *const backend, |
| struct log_msg_ids src_level, uint32_t timestamp, |
| const char *metadata, const uint8_t *data, uint32_t len); |
| |
| void (*dropped)(const struct log_backend *const backend, uint32_t cnt); |
| void (*panic)(const struct log_backend *const backend); |
| void (*init)(const struct log_backend *const backend); |
| }; |
| |
| /** |
| * @brief Logger backend control block. |
| */ |
| struct log_backend_control_block { |
| void *ctx; |
| uint8_t id; |
| bool active; |
| }; |
| |
| /** |
| * @brief Logger backend structure. |
| */ |
| struct log_backend { |
| const struct log_backend_api *api; |
| struct log_backend_control_block *cb; |
| const char *name; |
| bool autostart; |
| }; |
| |
| extern const struct log_backend __log_backends_start[]; |
| extern const struct log_backend __log_backends_end[]; |
| |
| /** |
| * @brief Macro for creating a logger backend instance. |
| * |
| * @param _name Name of the backend instance. |
| * @param _api Logger backend API. |
| * @param _autostart If true backend is initialized and activated together |
| * with the logger subsystem. |
| * @param ... Optional context. |
| */ |
| #define LOG_BACKEND_DEFINE(_name, _api, _autostart, ...) \ |
| static struct log_backend_control_block UTIL_CAT(backend_cb_, _name) = \ |
| { \ |
| COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \ |
| (), (.ctx = __VA_ARGS__,)) \ |
| .id = 0, \ |
| .active = false, \ |
| }; \ |
| static const STRUCT_SECTION_ITERABLE(log_backend, _name) = \ |
| { \ |
| .api = &_api, \ |
| .cb = &UTIL_CAT(backend_cb_, _name), \ |
| .name = STRINGIFY(_name), \ |
| .autostart = _autostart \ |
| } |
| |
| |
| /** |
| * @brief Put message with log entry to the backend. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @param[in] msg Pointer to message with log entry. |
| */ |
| static inline void log_backend_put(const struct log_backend *const backend, |
| struct log_msg *msg) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| __ASSERT_NO_MSG(msg != NULL); |
| backend->api->put(backend, msg); |
| } |
| |
| static inline void log_backend_msg2_process( |
| const struct log_backend *const backend, |
| union log_msg2_generic *msg) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| __ASSERT_NO_MSG(msg != NULL); |
| backend->api->process(backend, msg); |
| } |
| |
| |
| /** |
| * @brief Synchronously process log message. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @param[in] src_level Message details. |
| * @param[in] timestamp Timestamp. |
| * @param[in] fmt Log string. |
| * @param[in] ap Log string arguments. |
| */ |
| static inline void log_backend_put_sync_string( |
| const struct log_backend *const backend, |
| struct log_msg_ids src_level, |
| uint32_t timestamp, const char *fmt, |
| va_list ap) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| |
| if (backend->api->put_sync_string) { |
| backend->api->put_sync_string(backend, src_level, |
| timestamp, fmt, ap); |
| } |
| } |
| |
| /** |
| * @brief Synchronously process log hexdump_message. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @param[in] src_level Message details. |
| * @param[in] timestamp Timestamp. |
| * @param[in] metadata Raw string associated with the data. |
| * @param[in] data Data. |
| * @param[in] len Data length. |
| */ |
| static inline void log_backend_put_sync_hexdump( |
| const struct log_backend *const backend, |
| struct log_msg_ids src_level, |
| uint32_t timestamp, const char *metadata, |
| const uint8_t *data, uint32_t len) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| |
| if (backend->api->put_sync_hexdump) { |
| backend->api->put_sync_hexdump(backend, src_level, timestamp, |
| metadata, data, len); |
| } |
| } |
| |
| /** |
| * @brief Notify backend about dropped log messages. |
| * |
| * Function is optional. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @param[in] cnt Number of dropped logs since last notification. |
| */ |
| static inline void log_backend_dropped(const struct log_backend *const backend, |
| uint32_t cnt) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| |
| if (backend->api->dropped != NULL) { |
| backend->api->dropped(backend, cnt); |
| } |
| } |
| |
| /** |
| * @brief Reconfigure backend to panic mode. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| */ |
| static inline void log_backend_panic(const struct log_backend *const backend) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| backend->api->panic(backend); |
| } |
| |
| /** |
| * @brief Set backend id. |
| * |
| * @note It is used internally by the logger. |
| * |
| * @param backend Pointer to the backend instance. |
| * @param id ID. |
| */ |
| static inline void log_backend_id_set(const struct log_backend *const backend, |
| uint8_t id) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| backend->cb->id = id; |
| } |
| |
| /** |
| * @brief Get backend id. |
| * |
| * @note It is used internally by the logger. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @return Id. |
| */ |
| static inline uint8_t log_backend_id_get(const struct log_backend *const backend) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| return backend->cb->id; |
| } |
| |
| /** |
| * @brief Get backend. |
| * |
| * @param[in] idx Pointer to the backend instance. |
| * |
| * @return Pointer to the backend instance. |
| */ |
| static inline const struct log_backend *log_backend_get(uint32_t idx) |
| { |
| return &__log_backends_start[idx]; |
| } |
| |
| /** |
| * @brief Get number of backends. |
| * |
| * @return Number of backends. |
| */ |
| static inline int log_backend_count_get(void) |
| { |
| return __log_backends_end - __log_backends_start; |
| } |
| |
| /** |
| * @brief Activate backend. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * @param[in] ctx User context. |
| */ |
| static inline void log_backend_activate(const struct log_backend *const backend, |
| void *ctx) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| backend->cb->ctx = ctx; |
| backend->cb->active = true; |
| } |
| |
| /** |
| * @brief Deactivate backend. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| */ |
| static inline void log_backend_deactivate( |
| const struct log_backend *const backend) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| backend->cb->active = false; |
| } |
| |
| /** |
| * @brief Check state of the backend. |
| * |
| * @param[in] backend Pointer to the backend instance. |
| * |
| * @return True if backend is active, false otherwise. |
| */ |
| static inline bool log_backend_is_active( |
| const struct log_backend *const backend) |
| { |
| __ASSERT_NO_MSG(backend != NULL); |
| return backend->cb->active; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ */ |