LCOV - code coverage report
Current view: top level - zephyr/logging - log_backend.h Coverage Total Hit
Test: new.info Lines: 55.3 % 38 21
Test Date: 2025-09-05 16:43:28

            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            0 :         bool initialized;
      87              : 
      88              :         /* Initialization level. */
      89            0 :         uint8_t level;
      90              : };
      91              : 
      92              : /**
      93              :  * @brief Logger backend structure.
      94              :  */
      95            1 : struct log_backend {
      96            0 :         const struct log_backend_api *api;
      97            0 :         struct log_backend_control_block *cb;
      98            0 :         const char *name;
      99            0 :         bool autostart;
     100              : };
     101              : 
     102              : /**
     103              :  * @brief Macro for creating a logger backend instance.
     104              :  *
     105              :  * @param _name         Name of the backend instance.
     106              :  * @param _api          Logger backend API.
     107              :  * @param _autostart    If true backend is initialized and activated together
     108              :  *                      with the logger subsystem.
     109              :  * @param ...           Optional context.
     110              :  */
     111            1 : #define LOG_BACKEND_DEFINE(_name, _api, _autostart, ...)                       \
     112              :         static struct log_backend_control_block UTIL_CAT(backend_cb_, _name) = \
     113              :         {                                                                      \
     114              :                 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__),              \
     115              :                                 (), (.ctx = __VA_ARGS__,))                     \
     116              :                 .id = 0,                                                       \
     117              :                 .active = false,                                               \
     118              :         };                                                                     \
     119              :         static const STRUCT_SECTION_ITERABLE(log_backend, _name) =             \
     120              :         {                                                                      \
     121              :                 .api = &_api,                                                      \
     122              :                 .cb = &UTIL_CAT(backend_cb_, _name),                               \
     123              :                 .name = STRINGIFY(_name),                                      \
     124              :                 .autostart = _autostart                                        \
     125              :         }
     126              : 
     127              : 
     128              : /**
     129              :  * @brief Initialize or initiate the logging backend.
     130              :  *
     131              :  * If backend initialization takes longer time it could block logging thread
     132              :  * if backend is autostarted. That is because all backends are initialized in
     133              :  * the context of the logging thread. In that case, backend shall provide
     134              :  * function for polling for readiness (@ref log_backend_is_ready).
     135              :  *
     136              :  * @param[in] backend  Pointer to the backend instance.
     137              :  */
     138            1 : static inline void log_backend_init(const struct log_backend *const backend)
     139              : {
     140              :         __ASSERT_NO_MSG(backend != NULL);
     141              :         if (backend->api->init) {
     142              :                 backend->api->init(backend);
     143              :         }
     144              :         backend->cb->initialized = true;
     145              : }
     146              : 
     147              : /**
     148              :  * @brief Poll for backend readiness.
     149              :  *
     150              :  * If backend is ready immediately after initialization then backend may not
     151              :  * provide this function.
     152              :  *
     153              :  * @param[in] backend  Pointer to the backend instance.
     154              :  *
     155              :  * @retval 0 if backend is ready.
     156              :  * @retval -EBUSY if backend is not yet ready.
     157              :  */
     158            1 : static inline int log_backend_is_ready(const struct log_backend *const backend)
     159              : {
     160              :         __ASSERT_NO_MSG(backend != NULL);
     161              :         if (backend->api->is_ready != NULL) {
     162              :                 return backend->api->is_ready(backend);
     163              :         }
     164              : 
     165              :         return 0;
     166              : }
     167              : 
     168              : /**
     169              :  * @brief Process message.
     170              :  *
     171              :  * Function is used in deferred and immediate mode. On return, message content
     172              :  * is processed by the backend and memory can be freed.
     173              :  *
     174              :  * @param[in] backend  Pointer to the backend instance.
     175              :  * @param[in] msg      Pointer to message with log entry.
     176              :  */
     177            1 : static inline void log_backend_msg_process(const struct log_backend *const backend,
     178              :                                            union log_msg_generic *msg)
     179              : {
     180              :         __ASSERT_NO_MSG(backend != NULL);
     181              :         __ASSERT_NO_MSG(msg != NULL);
     182              :         backend->api->process(backend, msg);
     183              : }
     184              : 
     185              : /**
     186              :  * @brief Notify backend about dropped log messages.
     187              :  *
     188              :  * Function is optional.
     189              :  *
     190              :  * @param[in] backend  Pointer to the backend instance.
     191              :  * @param[in] cnt      Number of dropped logs since last notification.
     192              :  */
     193            1 : static inline void log_backend_dropped(const struct log_backend *const backend,
     194              :                                        uint32_t cnt)
     195              : {
     196              :         __ASSERT_NO_MSG(backend != NULL);
     197              : 
     198              :         if (backend->api->dropped != NULL) {
     199              :                 backend->api->dropped(backend, cnt);
     200              :         }
     201              : }
     202              : 
     203              : /**
     204              :  * @brief Reconfigure backend to panic mode.
     205              :  *
     206              :  * @param[in] backend  Pointer to the backend instance.
     207              :  */
     208            1 : static inline void log_backend_panic(const struct log_backend *const backend)
     209              : {
     210              :         __ASSERT_NO_MSG(backend != NULL);
     211              :         backend->api->panic(backend);
     212              : }
     213              : 
     214              : /**
     215              :  * @brief Set backend id.
     216              :  *
     217              :  * @note It is used internally by the logger.
     218              :  *
     219              :  * @param backend  Pointer to the backend instance.
     220              :  * @param id       ID.
     221              :  */
     222            1 : static inline void log_backend_id_set(const struct log_backend *const backend,
     223              :                                       uint8_t id)
     224              : {
     225              :         __ASSERT_NO_MSG(backend != NULL);
     226              :         backend->cb->id = id;
     227              : }
     228              : 
     229              : /**
     230              :  * @brief Get backend id.
     231              :  *
     232              :  * @note It is used internally by the logger.
     233              :  *
     234              :  * @param[in] backend  Pointer to the backend instance.
     235              :  * @return    Id.
     236              :  */
     237            1 : static inline uint8_t log_backend_id_get(const struct log_backend *const backend)
     238              : {
     239              :         __ASSERT_NO_MSG(backend != NULL);
     240              :         return backend->cb->id;
     241              : }
     242              : 
     243              : /**
     244              :  * @brief Get backend.
     245              :  *
     246              :  * @param[in] idx  Pointer to the backend instance.
     247              :  *
     248              :  * @return    Pointer to the backend instance.
     249              :  */
     250            1 : static inline const struct log_backend *log_backend_get(uint32_t idx)
     251              : {
     252              :         const struct log_backend *backend;
     253              : 
     254              :         STRUCT_SECTION_GET(log_backend, idx, &backend);
     255              : 
     256              :         return backend;
     257              : }
     258              : 
     259              : /**
     260              :  * @brief Get number of backends.
     261              :  *
     262              :  * @return Number of backends.
     263              :  */
     264            1 : static inline int log_backend_count_get(void)
     265              : {
     266              :         int cnt;
     267              : 
     268              :         STRUCT_SECTION_COUNT(log_backend, &cnt);
     269              : 
     270              :         return cnt;
     271              : }
     272              : 
     273              : /**
     274              :  * @brief Activate backend.
     275              :  *
     276              :  * @param[in] backend  Pointer to the backend instance.
     277              :  * @param[in] ctx      User context.
     278              :  */
     279            1 : static inline void log_backend_activate(const struct log_backend *const backend,
     280              :                                         void *ctx)
     281              : {
     282              :         __ASSERT_NO_MSG(backend != NULL);
     283              :         backend->cb->ctx = ctx;
     284              :         backend->cb->active = true;
     285              : }
     286              : 
     287              : /**
     288              :  * @brief Deactivate backend.
     289              :  *
     290              :  * @param[in] backend  Pointer to the backend instance.
     291              :  */
     292            1 : static inline void log_backend_deactivate(
     293              :                                 const struct log_backend *const backend)
     294              : {
     295              :         __ASSERT_NO_MSG(backend != NULL);
     296              :         backend->cb->active = false;
     297              : }
     298              : 
     299              : /**
     300              :  * @brief Check state of the backend.
     301              :  *
     302              :  * @param[in] backend  Pointer to the backend instance.
     303              :  *
     304              :  * @return True if backend is active, false otherwise.
     305              :  */
     306            1 : static inline bool log_backend_is_active(
     307              :                                 const struct log_backend *const backend)
     308              : {
     309              :         __ASSERT_NO_MSG(backend != NULL);
     310              :         return backend->cb->active;
     311              : }
     312              : 
     313              : /** @brief Set logging format.
     314              :  *
     315              :  * @param backend Pointer to the backend instance.
     316              :  * @param log_type Log format.
     317              :  *
     318              :  * @retval -ENOTSUP If the backend does not support changing format types.
     319              :  * @retval -EINVAL If the input is invalid.
     320              :  * @retval 0 for success.
     321              :  */
     322            1 : static inline int log_backend_format_set(const struct log_backend *backend, uint32_t log_type)
     323              : {
     324              :         extern size_t log_format_table_size(void);
     325              : 
     326              :         if ((size_t)log_type >= log_format_table_size()) {
     327              :                 return -EINVAL;
     328              :         }
     329              : 
     330              :         if (log_format_func_t_get(log_type) == NULL) {
     331              :                 return -EINVAL;
     332              :         }
     333              : 
     334              :         if (backend == NULL) {
     335              :                 return -EINVAL;
     336              :         }
     337              : 
     338              :         if (backend->api->format_set == NULL) {
     339              :                 return -ENOTSUP;
     340              :         }
     341              : 
     342              :         return backend->api->format_set(backend, log_type);
     343              : }
     344              : 
     345              : /**
     346              :  * @brief Notify a backend of an event.
     347              :  *
     348              :  * @param backend Pointer to the backend instance.
     349              :  * @param event Event to be notified.
     350              :  * @param arg Pointer to the argument(s).
     351              :  */
     352            1 : static inline void log_backend_notify(const struct log_backend *const backend,
     353              :                                       enum log_backend_evt event,
     354              :                                       union log_backend_evt_arg *arg)
     355              : {
     356              :         __ASSERT_NO_MSG(backend != NULL);
     357              : 
     358              :         if (backend->api->notify) {
     359              :                 backend->api->notify(backend, event, arg);
     360              :         }
     361              : }
     362              : 
     363              : /**
     364              :  * @}
     365              :  */
     366              : 
     367              : #ifdef __cplusplus
     368              : }
     369              : #endif
     370              : 
     371              : #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ */
        

Generated by: LCOV version 2.0-1