1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef SHELL_LOG_BACKEND_H__
8 #define SHELL_LOG_BACKEND_H__
9 
10 #include <zephyr.h>
11 #include <logging/log_backend.h>
12 #include <logging/log_output.h>
13 #include <sys/mpsc_pbuf.h>
14 #include <sys/atomic.h>
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 extern const struct log_backend_api log_backend_shell_api;
20 
21 /** @brief Shell log backend states. */
22 enum shell_log_backend_state {
23 	SHELL_LOG_BACKEND_UNINIT,
24 	SHELL_LOG_BACKEND_ENABLED,
25 	SHELL_LOG_BACKEND_DISABLED,
26 	SHELL_LOG_BACKEND_PANIC,
27 };
28 
29 /** @brief Shell log backend control block (RW data). */
30 struct shell_log_backend_control_block {
31 	atomic_t dropped_cnt;
32 	enum shell_log_backend_state state;
33 };
34 
35 /** @brief Shell log backend instance structure (RO data). */
36 struct shell_log_backend {
37 	const struct log_backend *backend;
38 	struct k_msgq *msgq;
39 	const struct log_output *log_output;
40 	struct shell_log_backend_control_block *control_block;
41 	uint32_t timeout;
42 	const struct mpsc_pbuf_buffer_config *mpsc_buffer_config;
43 	struct mpsc_pbuf_buffer *mpsc_buffer;
44 };
45 
46 /** @brief Shell log backend message structure. */
47 struct shell_log_backend_msg {
48 	struct log_msg *msg;
49 	uint32_t timestamp;
50 };
51 
52 /** @brief Prototype of function outputing processed data. */
53 int z_shell_log_backend_output_func(uint8_t *data, size_t length, void *ctx);
54 
55 /** @def Z_SHELL_LOG_BACKEND_DEFINE
56  *  @brief Macro for creating instance of shell log backend.
57  *
58  *  @param _name	Shell name.
59  *  @param _buf		Output buffer.
60  *  @param _size	Output buffer size.
61  *  @param _queue_size	Log message queue size.
62  *  @param _timeout	Timeout in milliseconds for pending on queue full.
63  *			Message is dropped on timeout.
64  */
65 /** @def Z_SHELL_LOG_BACKEND_PTR
66  *  @brief Macro for retrieving pointer to the instance of shell log backend.
67  *
68  *  @param _name Shell name.
69  */
70 #ifdef CONFIG_SHELL_LOG_BACKEND
71 #define Z_SHELL_LOG_BACKEND_DEFINE(_name, _buf, _size, _queue_size, _timeout) \
72 	LOG_BACKEND_DEFINE(_name##_backend, log_backend_shell_api, false); \
73 	K_MSGQ_DEFINE(_name##_msgq, sizeof(struct shell_log_backend_msg), \
74 			_queue_size, sizeof(void *)); \
75 	LOG_OUTPUT_DEFINE(_name##_log_output, z_shell_log_backend_output_func,\
76 			  _buf, _size); \
77 	static struct shell_log_backend_control_block _name##_control_block; \
78 	static uint32_t __aligned(Z_LOG_MSG2_ALIGNMENT) _name##_buf[128]; \
79 	const struct mpsc_pbuf_buffer_config _name##_mpsc_buffer_config = { \
80 		.buf = _name##_buf, \
81 		.size = ARRAY_SIZE(_name##_buf), \
82 		.notify_drop = NULL, \
83 		.get_wlen = log_msg2_generic_get_wlen, \
84 		.flags = MPSC_PBUF_MODE_OVERWRITE, \
85 	}; \
86 	struct mpsc_pbuf_buffer _name##_mpsc_buffer; \
87 	static const struct shell_log_backend _name##_log_backend = { \
88 		.backend = &_name##_backend, \
89 		.msgq = IS_ENABLED(CONFIG_LOG_MODE_DEFERRED) ? \
90 			&_name##_msgq : NULL, \
91 		.log_output = &_name##_log_output, \
92 		.control_block = &_name##_control_block, \
93 		.timeout = _timeout, \
94 		.mpsc_buffer_config = IS_ENABLED(CONFIG_LOG2_MODE_DEFERRED) ? \
95 			&_name##_mpsc_buffer_config : NULL, \
96 		.mpsc_buffer = IS_ENABLED(CONFIG_LOG2_MODE_DEFERRED) ? \
97 			&_name##_mpsc_buffer : NULL, \
98 	}
99 
100 #define Z_SHELL_LOG_BACKEND_PTR(_name) (&_name##_log_backend)
101 #else /* CONFIG_LOG */
102 #define Z_SHELL_LOG_BACKEND_DEFINE(_name, _buf, _size, _queue_size, _timeout)
103 #define Z_SHELL_LOG_BACKEND_PTR(_name) NULL
104 #endif /* CONFIG_LOG */
105 
106 /** @brief Enable shell log backend.
107  *
108  * @param backend		Shell log backend instance.
109  * @param ctx			Pointer to shell instance.
110  * @param init_log_level	Initial log level set to all logging sources.
111  */
112 void z_shell_log_backend_enable(const struct shell_log_backend *backend,
113 				void *ctx, uint32_t init_log_level);
114 
115 /** @brief Disable shell log backend.
116  *
117  * @param backend Shell log backend instance.
118  */
119 void z_shell_log_backend_disable(const struct shell_log_backend *backend);
120 
121 /** @brief Trigger processing of one log entry.
122  *
123  * @param backend Shell log backend instance.
124  *
125  * @return True if message was processed, false if FIFO was empty
126  */
127 bool z_shell_log_backend_process(const struct shell_log_backend *backend);
128 
129 #ifdef __cplusplus
130 }
131 #endif
132 
133 #endif /* SHELL_LOG_BACKEND_H__ */
134