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_ */
|