LCOV - code coverage report
Current view: top level - zephyr/logging - log_backend.h Hit Total Coverage
Test: new.info Lines: 21 37 56.8 %
Date: 2025-01-09 21:13:38

          Line data    Source code
       1           0 : /*
       2             :  * Copyright (c) 2018 Nordic Semiconductor ASA
       3             :  *
       4             :  * SPDX-License-Identifier: Apache-2.0
       5             :  */
       6             : #ifndef ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_
       7             : #define ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_
       8             : 
       9             : #include <zephyr/logging/log_msg.h>
      10             : #include <stdarg.h>
      11             : #include <zephyr/sys/__assert.h>
      12             : #include <zephyr/sys/util.h>
      13             : #include <zephyr/logging/log_output.h>
      14             : #include <zephyr/sys/iterable_sections.h>
      15             : 
      16             : #ifdef __cplusplus
      17             : extern "C" {
      18             : #endif
      19             : 
      20             : /**
      21             :  * @brief Logger backend interface
      22             :  * @defgroup log_backend Logger backend interface
      23             :  * @ingroup logger
      24             :  * @{
      25             :  */
      26             : 
      27             : /* Forward declaration of the log_backend type. */
      28             : struct log_backend;
      29             : 
      30             : 
      31             : /**
      32             :  * @brief Backend events
      33             :  */
      34           1 : enum log_backend_evt {
      35             :         /**
      36             :          * @brief Event when process thread finishes processing.
      37             :          *
      38             :          * This event is emitted when the process thread finishes
      39             :          * processing pending log messages.
      40             :          *
      41             :          * @note This is not emitted when there are no pending
      42             :          *       log messages being processed.
      43             :          *
      44             :          * @note Deferred mode only.
      45             :          */
      46             :         LOG_BACKEND_EVT_PROCESS_THREAD_DONE,
      47             : 
      48             :         /** @brief Maximum number of backend events */
      49             :         LOG_BACKEND_EVT_MAX,
      50             : };
      51             : 
      52             : /**
      53             :  * @brief Argument(s) for backend events.
      54             :  */
      55           1 : union log_backend_evt_arg {
      56             :         /** @brief Unspecified argument(s). */
      57           1 :         void *raw;
      58             : };
      59             : 
      60             : /**
      61             :  * @brief Logger backend API.
      62             :  */
      63           1 : struct log_backend_api {
      64           0 :         void (*process)(const struct log_backend *const backend,
      65             :                         union log_msg_generic *msg);
      66             : 
      67           0 :         void (*dropped)(const struct log_backend *const backend, uint32_t cnt);
      68           0 :         void (*panic)(const struct log_backend *const backend);
      69           0 :         void (*init)(const struct log_backend *const backend);
      70           0 :         int (*is_ready)(const struct log_backend *const backend);
      71           0 :         int (*format_set)(const struct log_backend *const backend,
      72             :                                 uint32_t log_type);
      73             : 
      74           0 :         void (*notify)(const struct log_backend *const backend,
      75             :                        enum log_backend_evt event,
      76             :                        union log_backend_evt_arg *arg);
      77             : };
      78             : 
      79             : /**
      80             :  * @brief Logger backend control block.
      81             :  */
      82           1 : struct log_backend_control_block {
      83           0 :         void *ctx;
      84           0 :         uint8_t id;
      85           0 :         bool active;
      86             : 
      87             :         /* Initialization level. */
      88           0 :         uint8_t level;
      89             : };
      90             : 
      91             : /**
      92             :  * @brief Logger backend structure.
      93             :  */
      94           1 : struct log_backend {
      95           0 :         const struct log_backend_api *api;
      96           0 :         struct log_backend_control_block *cb;
      97           0 :         const char *name;
      98           0 :         bool autostart;
      99             : };
     100             : 
     101             : /**
     102             :  * @brief Macro for creating a logger backend instance.
     103             :  *
     104             :  * @param _name         Name of the backend instance.
     105             :  * @param _api          Logger backend API.
     106             :  * @param _autostart    If true backend is initialized and activated together
     107             :  *                      with the logger subsystem.
     108             :  * @param ...           Optional context.
     109             :  */
     110           1 : #define LOG_BACKEND_DEFINE(_name, _api, _autostart, ...)                       \
     111             :         static struct log_backend_control_block UTIL_CAT(backend_cb_, _name) = \
     112             :         {                                                                      \
     113             :                 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__),              \
     114             :                                 (), (.ctx = __VA_ARGS__,))                     \
     115             :                 .id = 0,                                                       \
     116             :                 .active = false,                                               \
     117             :         };                                                                     \
     118             :         static const STRUCT_SECTION_ITERABLE(log_backend, _name) =             \
     119             :         {                                                                      \
     120             :                 .api = &_api,                                                      \
     121             :                 .cb = &UTIL_CAT(backend_cb_, _name),                               \
     122             :                 .name = STRINGIFY(_name),                                      \
     123             :                 .autostart = _autostart                                        \
     124             :         }
     125             : 
     126             : 
     127             : /**
     128             :  * @brief Initialize or initiate the logging backend.
     129             :  *
     130             :  * If backend initialization takes longer time it could block logging thread
     131             :  * if backend is autostarted. That is because all backends are initialized in
     132             :  * the context of the logging thread. In that case, backend shall provide
     133             :  * function for polling for readiness (@ref log_backend_is_ready).
     134             :  *
     135             :  * @param[in] backend  Pointer to the backend instance.
     136             :  */
     137           1 : static inline void log_backend_init(const struct log_backend *const backend)
     138             : {
     139             :         __ASSERT_NO_MSG(backend != NULL);
     140             :         if (backend->api->init) {
     141             :                 backend->api->init(backend);
     142             :         }
     143             : }
     144             : 
     145             : /**
     146             :  * @brief Poll for backend readiness.
     147             :  *
     148             :  * If backend is ready immediately after initialization then backend may not
     149             :  * provide this function.
     150             :  *
     151             :  * @param[in] backend  Pointer to the backend instance.
     152             :  *
     153             :  * @retval 0 if backend is ready.
     154             :  * @retval -EBUSY if backend is not yet ready.
     155             :  */
     156           1 : static inline int log_backend_is_ready(const struct log_backend *const backend)
     157             : {
     158             :         __ASSERT_NO_MSG(backend != NULL);
     159             :         if (backend->api->is_ready != NULL) {
     160             :                 return backend->api->is_ready(backend);
     161             :         }
     162             : 
     163             :         return 0;
     164             : }
     165             : 
     166             : /**
     167             :  * @brief Process message.
     168             :  *
     169             :  * Function is used in deferred and immediate mode. On return, message content
     170             :  * is processed by the backend and memory can be freed.
     171             :  *
     172             :  * @param[in] backend  Pointer to the backend instance.
     173             :  * @param[in] msg      Pointer to message with log entry.
     174             :  */
     175           1 : static inline void log_backend_msg_process(const struct log_backend *const backend,
     176             :                                            union log_msg_generic *msg)
     177             : {
     178             :         __ASSERT_NO_MSG(backend != NULL);
     179             :         __ASSERT_NO_MSG(msg != NULL);
     180             :         backend->api->process(backend, msg);
     181             : }
     182             : 
     183             : /**
     184             :  * @brief Notify backend about dropped log messages.
     185             :  *
     186             :  * Function is optional.
     187             :  *
     188             :  * @param[in] backend  Pointer to the backend instance.
     189             :  * @param[in] cnt      Number of dropped logs since last notification.
     190             :  */
     191           1 : static inline void log_backend_dropped(const struct log_backend *const backend,
     192             :                                        uint32_t cnt)
     193             : {
     194             :         __ASSERT_NO_MSG(backend != NULL);
     195             : 
     196             :         if (backend->api->dropped != NULL) {
     197             :                 backend->api->dropped(backend, cnt);
     198             :         }
     199             : }
     200             : 
     201             : /**
     202             :  * @brief Reconfigure backend to panic mode.
     203             :  *
     204             :  * @param[in] backend  Pointer to the backend instance.
     205             :  */
     206           1 : static inline void log_backend_panic(const struct log_backend *const backend)
     207             : {
     208             :         __ASSERT_NO_MSG(backend != NULL);
     209             :         backend->api->panic(backend);
     210             : }
     211             : 
     212             : /**
     213             :  * @brief Set backend id.
     214             :  *
     215             :  * @note It is used internally by the logger.
     216             :  *
     217             :  * @param backend  Pointer to the backend instance.
     218             :  * @param id       ID.
     219             :  */
     220           1 : static inline void log_backend_id_set(const struct log_backend *const backend,
     221             :                                       uint8_t id)
     222             : {
     223             :         __ASSERT_NO_MSG(backend != NULL);
     224             :         backend->cb->id = id;
     225             : }
     226             : 
     227             : /**
     228             :  * @brief Get backend id.
     229             :  *
     230             :  * @note It is used internally by the logger.
     231             :  *
     232             :  * @param[in] backend  Pointer to the backend instance.
     233             :  * @return    Id.
     234             :  */
     235           1 : static inline uint8_t log_backend_id_get(const struct log_backend *const backend)
     236             : {
     237             :         __ASSERT_NO_MSG(backend != NULL);
     238             :         return backend->cb->id;
     239             : }
     240             : 
     241             : /**
     242             :  * @brief Get backend.
     243             :  *
     244             :  * @param[in] idx  Pointer to the backend instance.
     245             :  *
     246             :  * @return    Pointer to the backend instance.
     247             :  */
     248           1 : static inline const struct log_backend *log_backend_get(uint32_t idx)
     249             : {
     250             :         const struct log_backend *backend;
     251             : 
     252             :         STRUCT_SECTION_GET(log_backend, idx, &backend);
     253             : 
     254             :         return backend;
     255             : }
     256             : 
     257             : /**
     258             :  * @brief Get number of backends.
     259             :  *
     260             :  * @return Number of backends.
     261             :  */
     262           1 : static inline int log_backend_count_get(void)
     263             : {
     264             :         int cnt;
     265             : 
     266             :         STRUCT_SECTION_COUNT(log_backend, &cnt);
     267             : 
     268             :         return cnt;
     269             : }
     270             : 
     271             : /**
     272             :  * @brief Activate backend.
     273             :  *
     274             :  * @param[in] backend  Pointer to the backend instance.
     275             :  * @param[in] ctx      User context.
     276             :  */
     277           1 : static inline void log_backend_activate(const struct log_backend *const backend,
     278             :                                         void *ctx)
     279             : {
     280             :         __ASSERT_NO_MSG(backend != NULL);
     281             :         backend->cb->ctx = ctx;
     282             :         backend->cb->active = true;
     283             : }
     284             : 
     285             : /**
     286             :  * @brief Deactivate backend.
     287             :  *
     288             :  * @param[in] backend  Pointer to the backend instance.
     289             :  */
     290           1 : static inline void log_backend_deactivate(
     291             :                                 const struct log_backend *const backend)
     292             : {
     293             :         __ASSERT_NO_MSG(backend != NULL);
     294             :         backend->cb->active = false;
     295             : }
     296             : 
     297             : /**
     298             :  * @brief Check state of the backend.
     299             :  *
     300             :  * @param[in] backend  Pointer to the backend instance.
     301             :  *
     302             :  * @return True if backend is active, false otherwise.
     303             :  */
     304           1 : static inline bool log_backend_is_active(
     305             :                                 const struct log_backend *const backend)
     306             : {
     307             :         __ASSERT_NO_MSG(backend != NULL);
     308             :         return backend->cb->active;
     309             : }
     310             : 
     311             : /** @brief Set logging format.
     312             :  *
     313             :  * @param backend Pointer to the backend instance.
     314             :  * @param log_type Log format.
     315             :  *
     316             :  * @retval -ENOTSUP If the backend does not support changing format types.
     317             :  * @retval -EINVAL If the input is invalid.
     318             :  * @retval 0 for success.
     319             :  */
     320           1 : static inline int log_backend_format_set(const struct log_backend *backend, uint32_t log_type)
     321             : {
     322             :         extern size_t log_format_table_size(void);
     323             : 
     324             :         if ((size_t)log_type >= log_format_table_size()) {
     325             :                 return -EINVAL;
     326             :         }
     327             : 
     328             :         if (log_format_func_t_get(log_type) == NULL) {
     329             :                 return -EINVAL;
     330             :         }
     331             : 
     332             :         if (backend == NULL) {
     333             :                 return -EINVAL;
     334             :         }
     335             : 
     336             :         if (backend->api->format_set == NULL) {
     337             :                 return -ENOTSUP;
     338             :         }
     339             : 
     340             :         return backend->api->format_set(backend, log_type);
     341             : }
     342             : 
     343             : /**
     344             :  * @brief Notify a backend of an event.
     345             :  *
     346             :  * @param backend Pointer to the backend instance.
     347             :  * @param event Event to be notified.
     348             :  * @param arg Pointer to the argument(s).
     349             :  */
     350           1 : static inline void log_backend_notify(const struct log_backend *const backend,
     351             :                                       enum log_backend_evt event,
     352             :                                       union log_backend_evt_arg *arg)
     353             : {
     354             :         __ASSERT_NO_MSG(backend != NULL);
     355             : 
     356             :         if (backend->api->notify) {
     357             :                 backend->api->notify(backend, event, arg);
     358             :         }
     359             : }
     360             : 
     361             : /**
     362             :  * @}
     363             :  */
     364             : 
     365             : #ifdef __cplusplus
     366             : }
     367             : #endif
     368             : 
     369             : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ */

Generated by: LCOV version 1.14