1 /*
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 <logging/log_msg.h>
10 #include <logging/log_msg2.h>
11 #include <stdarg.h>
12 #include <sys/__assert.h>
13 #include <sys/util.h>
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 /**
20 * @brief Logger backend interface
21 * @defgroup log_backend Logger backend interface
22 * @ingroup logger
23 * @{
24 */
25
26 /* Forward declaration of the log_backend type. */
27 struct log_backend;
28
29 /**
30 * @brief Logger backend API.
31 */
32 struct log_backend_api {
33 void (*process)(const struct log_backend *const backend,
34 union log_msg2_generic *msg);
35
36 void (*put)(const struct log_backend *const backend,
37 struct log_msg *msg);
38 void (*put_sync_string)(const struct log_backend *const backend,
39 struct log_msg_ids src_level, uint32_t timestamp,
40 const char *fmt, va_list ap);
41 void (*put_sync_hexdump)(const struct log_backend *const backend,
42 struct log_msg_ids src_level, uint32_t timestamp,
43 const char *metadata, const uint8_t *data, uint32_t len);
44
45 void (*dropped)(const struct log_backend *const backend, uint32_t cnt);
46 void (*panic)(const struct log_backend *const backend);
47 void (*init)(const struct log_backend *const backend);
48 };
49
50 /**
51 * @brief Logger backend control block.
52 */
53 struct log_backend_control_block {
54 void *ctx;
55 uint8_t id;
56 bool active;
57 };
58
59 /**
60 * @brief Logger backend structure.
61 */
62 struct log_backend {
63 const struct log_backend_api *api;
64 struct log_backend_control_block *cb;
65 const char *name;
66 bool autostart;
67 };
68
69 extern const struct log_backend __log_backends_start[];
70 extern const struct log_backend __log_backends_end[];
71
72 /**
73 * @brief Macro for creating a logger backend instance.
74 *
75 * @param _name Name of the backend instance.
76 * @param _api Logger backend API.
77 * @param _autostart If true backend is initialized and activated together
78 * with the logger subsystem.
79 * @param ... Optional context.
80 */
81 #define LOG_BACKEND_DEFINE(_name, _api, _autostart, ...) \
82 static struct log_backend_control_block UTIL_CAT(backend_cb_, _name) = \
83 { \
84 COND_CODE_0(NUM_VA_ARGS_LESS_1(_, ##__VA_ARGS__), \
85 (), (.ctx = __VA_ARGS__,)) \
86 .id = 0, \
87 .active = false, \
88 }; \
89 static const STRUCT_SECTION_ITERABLE(log_backend, _name) = \
90 { \
91 .api = &_api, \
92 .cb = &UTIL_CAT(backend_cb_, _name), \
93 .name = STRINGIFY(_name), \
94 .autostart = _autostart \
95 }
96
97
98 /**
99 * @brief Put message with log entry to the backend.
100 *
101 * @param[in] backend Pointer to the backend instance.
102 * @param[in] msg Pointer to message with log entry.
103 */
log_backend_put(const struct log_backend * const backend,struct log_msg * msg)104 static inline void log_backend_put(const struct log_backend *const backend,
105 struct log_msg *msg)
106 {
107 __ASSERT_NO_MSG(backend != NULL);
108 __ASSERT_NO_MSG(msg != NULL);
109 backend->api->put(backend, msg);
110 }
111
log_backend_msg2_process(const struct log_backend * const backend,union log_msg2_generic * msg)112 static inline void log_backend_msg2_process(
113 const struct log_backend *const backend,
114 union log_msg2_generic *msg)
115 {
116 __ASSERT_NO_MSG(backend != NULL);
117 __ASSERT_NO_MSG(msg != NULL);
118 backend->api->process(backend, msg);
119 }
120
121
122 /**
123 * @brief Synchronously process log message.
124 *
125 * @param[in] backend Pointer to the backend instance.
126 * @param[in] src_level Message details.
127 * @param[in] timestamp Timestamp.
128 * @param[in] fmt Log string.
129 * @param[in] ap Log string arguments.
130 */
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)131 static inline void log_backend_put_sync_string(
132 const struct log_backend *const backend,
133 struct log_msg_ids src_level,
134 uint32_t timestamp, const char *fmt,
135 va_list ap)
136 {
137 __ASSERT_NO_MSG(backend != NULL);
138
139 if (backend->api->put_sync_string) {
140 backend->api->put_sync_string(backend, src_level,
141 timestamp, fmt, ap);
142 }
143 }
144
145 /**
146 * @brief Synchronously process log hexdump_message.
147 *
148 * @param[in] backend Pointer to the backend instance.
149 * @param[in] src_level Message details.
150 * @param[in] timestamp Timestamp.
151 * @param[in] metadata Raw string associated with the data.
152 * @param[in] data Data.
153 * @param[in] len Data length.
154 */
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)155 static inline void log_backend_put_sync_hexdump(
156 const struct log_backend *const backend,
157 struct log_msg_ids src_level,
158 uint32_t timestamp, const char *metadata,
159 const uint8_t *data, uint32_t len)
160 {
161 __ASSERT_NO_MSG(backend != NULL);
162
163 if (backend->api->put_sync_hexdump) {
164 backend->api->put_sync_hexdump(backend, src_level, timestamp,
165 metadata, data, len);
166 }
167 }
168
169 /**
170 * @brief Notify backend about dropped log messages.
171 *
172 * Function is optional.
173 *
174 * @param[in] backend Pointer to the backend instance.
175 * @param[in] cnt Number of dropped logs since last notification.
176 */
log_backend_dropped(const struct log_backend * const backend,uint32_t cnt)177 static inline void log_backend_dropped(const struct log_backend *const backend,
178 uint32_t cnt)
179 {
180 __ASSERT_NO_MSG(backend != NULL);
181
182 if (backend->api->dropped != NULL) {
183 backend->api->dropped(backend, cnt);
184 }
185 }
186
187 /**
188 * @brief Reconfigure backend to panic mode.
189 *
190 * @param[in] backend Pointer to the backend instance.
191 */
log_backend_panic(const struct log_backend * const backend)192 static inline void log_backend_panic(const struct log_backend *const backend)
193 {
194 __ASSERT_NO_MSG(backend != NULL);
195 backend->api->panic(backend);
196 }
197
198 /**
199 * @brief Set backend id.
200 *
201 * @note It is used internally by the logger.
202 *
203 * @param backend Pointer to the backend instance.
204 * @param id ID.
205 */
log_backend_id_set(const struct log_backend * const backend,uint8_t id)206 static inline void log_backend_id_set(const struct log_backend *const backend,
207 uint8_t id)
208 {
209 __ASSERT_NO_MSG(backend != NULL);
210 backend->cb->id = id;
211 }
212
213 /**
214 * @brief Get backend id.
215 *
216 * @note It is used internally by the logger.
217 *
218 * @param[in] backend Pointer to the backend instance.
219 * @return Id.
220 */
log_backend_id_get(const struct log_backend * const backend)221 static inline uint8_t log_backend_id_get(const struct log_backend *const backend)
222 {
223 __ASSERT_NO_MSG(backend != NULL);
224 return backend->cb->id;
225 }
226
227 /**
228 * @brief Get backend.
229 *
230 * @param[in] idx Pointer to the backend instance.
231 *
232 * @return Pointer to the backend instance.
233 */
log_backend_get(uint32_t idx)234 static inline const struct log_backend *log_backend_get(uint32_t idx)
235 {
236 return &__log_backends_start[idx];
237 }
238
239 /**
240 * @brief Get number of backends.
241 *
242 * @return Number of backends.
243 */
log_backend_count_get(void)244 static inline int log_backend_count_get(void)
245 {
246 return __log_backends_end - __log_backends_start;
247 }
248
249 /**
250 * @brief Activate backend.
251 *
252 * @param[in] backend Pointer to the backend instance.
253 * @param[in] ctx User context.
254 */
log_backend_activate(const struct log_backend * const backend,void * ctx)255 static inline void log_backend_activate(const struct log_backend *const backend,
256 void *ctx)
257 {
258 __ASSERT_NO_MSG(backend != NULL);
259 backend->cb->ctx = ctx;
260 backend->cb->active = true;
261 }
262
263 /**
264 * @brief Deactivate backend.
265 *
266 * @param[in] backend Pointer to the backend instance.
267 */
log_backend_deactivate(const struct log_backend * const backend)268 static inline void log_backend_deactivate(
269 const struct log_backend *const backend)
270 {
271 __ASSERT_NO_MSG(backend != NULL);
272 backend->cb->active = false;
273 }
274
275 /**
276 * @brief Check state of the backend.
277 *
278 * @param[in] backend Pointer to the backend instance.
279 *
280 * @return True if backend is active, false otherwise.
281 */
log_backend_is_active(const struct log_backend * const backend)282 static inline bool log_backend_is_active(
283 const struct log_backend *const backend)
284 {
285 __ASSERT_NO_MSG(backend != NULL);
286 return backend->cb->active;
287 }
288
289 /**
290 * @}
291 */
292
293 #ifdef __cplusplus
294 }
295 #endif
296
297 #endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_H_ */
298