1 /*
2  * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #ifndef ZEPHYR_INCLUDE_ZBUS_H_
7 #define ZEPHYR_INCLUDE_ZBUS_H_
8 
9 #include <string.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/sys/iterable_sections.h>
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Zbus API
20  * @defgroup zbus_apis Zbus APIs
21  * @ingroup os_services
22  * @{
23  */
24 
25 /**
26  * @brief Type used to represent a channel mutable data.
27  *
28  * Every channel has a zbus_channel_data structure associated.
29  */
30 struct zbus_channel_data {
31 	/** Static channel observer list start index. Considering the ITERABLE SECTIONS allocation
32 	 * order.
33 	 */
34 	int16_t observers_start_idx;
35 
36 	/** Static channel observer list end index. Considering the ITERABLE SECTIONS allocation
37 	 * order.
38 	 */
39 	int16_t observers_end_idx;
40 
41 	/** Access control semaphore. Points to the semaphore used to avoid race conditions
42 	 * for accessing the channel.
43 	 */
44 	struct k_sem sem;
45 
46 #if defined(CONFIG_ZBUS_PRIORITY_BOOST)
47 	/** Highest observer priority. Indicates the priority that the VDED will use to boost the
48 	 * notification process avoiding preemptions.
49 	 */
50 	int highest_observer_priority;
51 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
52 
53 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
54 	/** Channel observer list. Represents the channel's observers list, it can be empty
55 	 * or have listeners and subscribers mixed in any sequence. It can be changed in runtime.
56 	 */
57 	sys_slist_t observers;
58 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
59 
60 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
61 	/** Net buf pool for message subscribers. It can be either the global or a separated one.
62 	 */
63 	struct net_buf_pool *msg_subscriber_pool;
64 #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
65 };
66 
67 /**
68  * @brief Type used to represent a channel.
69  *
70  * Every channel has a zbus_channel structure associated used to control the channel
71  * access and usage.
72  */
73 struct zbus_channel {
74 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
75 	/** Channel name. */
76 	const char *const name;
77 #endif
78 	/** Message reference. Represents the message's reference that points to the actual
79 	 * shared memory region.
80 	 */
81 	void *const message;
82 
83 	/** Message size. Represents the channel's message size. */
84 	const size_t message_size;
85 
86 	/** User data available to extend zbus features. The channel must be claimed before
87 	 * using this field.
88 	 */
89 	void *const user_data;
90 
91 	/** Message validator. Stores the reference to the function to check the message
92 	 * validity before actually performing the publishing. No invalid messages can be
93 	 * published. Every message is valid when this field is empty.
94 	 */
95 	bool (*const validator)(const void *msg, size_t msg_size);
96 
97 	/** Mutable channel data struct. */
98 	struct zbus_channel_data *const data;
99 };
100 
101 /**
102  * @brief Type used to represent an observer type.
103  *
104  * A observer can be a listener or a subscriber.
105  */
106 enum __packed zbus_observer_type {
107 	ZBUS_OBSERVER_LISTENER_TYPE,
108 	ZBUS_OBSERVER_SUBSCRIBER_TYPE,
109 	ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE,
110 };
111 
112 struct zbus_observer_data {
113 	/** Enabled flag. Indicates if observer is receiving notification. */
114 	bool enabled;
115 
116 #if defined(CONFIG_ZBUS_PRIORITY_BOOST)
117 	/** Subscriber attached thread priority. */
118 	int priority;
119 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
120 };
121 
122 /**
123  * @brief Type used to represent an observer.
124  *
125  * Every observer has an representation structure containing the relevant information.
126  * An observer is a code portion interested in some channel. The observer can be notified
127  * synchronously or asynchronously and it is called listener and subscriber respectively.
128  * The observer can be enabled or disabled during runtime by change the enabled boolean
129  * field of the structure. The listeners have a callback function that is executed by the
130  * bus with the index of the changed channel as argument when the notification is sent.
131  * The subscribers have a message queue where the bus enqueues the index of the changed
132  * channel when a notification is sent.
133  *
134  * @see zbus_obs_set_enable function to properly change the observer's enabled field.
135  *
136  */
137 struct zbus_observer {
138 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
139 	/** Observer name. */
140 	const char *const name;
141 #endif
142 	/** Type indication. */
143 	enum zbus_observer_type type;
144 
145 	/** Mutable observer data struct. */
146 	struct zbus_observer_data *const data;
147 
148 	union {
149 		/** Observer message queue. It turns the observer into a subscriber. */
150 		struct k_msgq *const queue;
151 
152 		/** Observer callback function. It turns the observer into a listener. */
153 		void (*const callback)(const struct zbus_channel *chan);
154 
155 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
156 		/** Observer message FIFO. It turns the observer into a message subscriber. It only
157 		 * exists if the @kconfig{CONFIG_ZBUS_MSG_SUBSCRIBER} is enabled.
158 		 */
159 		struct k_fifo *const message_fifo;
160 #endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
161 	};
162 };
163 
164 /** @cond INTERNAL_HIDDEN */
165 struct zbus_channel_observation_mask {
166 	bool enabled;
167 };
168 
169 struct zbus_channel_observation {
170 	const struct zbus_channel *const chan;
171 	const struct zbus_observer *const obs;
172 };
173 
174 #ifdef __cplusplus
175 #define _ZBUS_CPP_EXTERN extern
176 #else
177 #define _ZBUS_CPP_EXTERN
178 #endif /* __cplusplus */
179 
180 #define ZBUS_MIN_THREAD_PRIORITY (CONFIG_NUM_PREEMPT_PRIORITIES - 1)
181 
182 #if defined(CONFIG_ZBUS_ASSERT_MOCK)
183 #define _ZBUS_ASSERT(_cond, _fmt, ...)                                                             \
184 	do {                                                                                       \
185 		if (!(_cond)) {                                                                    \
186 			printk("ZBUS ASSERT: ");                                                   \
187 			printk(_fmt, ##__VA_ARGS__);                                               \
188 			printk("\n");                                                              \
189 			return -EFAULT;                                                            \
190 		}                                                                                  \
191 	} while (0)
192 #else
193 #define _ZBUS_ASSERT(_cond, _fmt, ...) __ASSERT(_cond, _fmt, ##__VA_ARGS__)
194 #endif
195 
196 #if defined(CONFIG_ZBUS_CHANNEL_NAME)
197 #define ZBUS_CHANNEL_NAME_INIT(_name) .name = #_name,
198 #define _ZBUS_CHAN_NAME(_chan)        (_chan)->name
199 #else
200 #define ZBUS_CHANNEL_NAME_INIT(_name)
201 #define _ZBUS_CHAN_NAME(_chan) ""
202 #endif
203 
204 #if defined(CONFIG_ZBUS_OBSERVER_NAME)
205 #define ZBUS_OBSERVER_NAME_INIT(_name) .name = #_name,
206 #define _ZBUS_OBS_NAME(_obs)           (_obs)->name
207 #else
208 #define ZBUS_OBSERVER_NAME_INIT(_name)
209 #define _ZBUS_OBS_NAME(_obs) ""
210 #endif
211 
212 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS)
213 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name) static sys_slist_t _slist_name
214 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) .runtime_observers = &_slist_name,
215 #else
216 #define ZBUS_RUNTIME_OBSERVERS_LIST_DECL(_slist_name)
217 #define ZBUS_RUNTIME_OBSERVERS_LIST_INIT(_slist_name) /* No runtime observers */
218 #endif
219 
220 #define _ZBUS_OBS_EXTERN(_name) extern struct zbus_observer _name
221 
222 #define _ZBUS_CHAN_EXTERN(_name) extern const struct zbus_channel _name
223 
224 #define ZBUS_REF(_value) &(_value)
225 
226 #define FOR_EACH_FIXED_ARG_NONEMPTY_TERM(F, sep, fixed_arg, ...)                                   \
227 	COND_CODE_0(/* are there zero non-empty arguments ? */                                     \
228 		    NUM_VA_ARGS_LESS_1(                                                            \
229 			    LIST_DROP_EMPTY(__VA_ARGS__, _)), /* if so, expand to nothing */       \
230 		    (),                                       /* otherwise, expand to: */          \
231 		    (FOR_EACH_IDX_FIXED_ARG(                                                       \
232 			    F, sep, fixed_arg,                                                     \
233 			    LIST_DROP_EMPTY(__VA_ARGS__)) /* plus a final terminator */            \
234 		     __DEBRACKET sep))
235 
236 #define _ZBUS_OBSERVATION_PREFIX(_idx)                                                             \
237 	GET_ARG_N(_idx, 00, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17,    \
238 		  18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,  \
239 		  38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,  \
240 		  58, 59, 60, 61, 62, 63)
241 
242 #define _ZBUS_CHAN_OBSERVATION(_idx, _obs, _chan)                                                  \
243 	const STRUCT_SECTION_ITERABLE(                                                             \
244 		zbus_channel_observation,                                                          \
245 		_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx)))) = {.chan = &_chan,       \
246 									     .obs = &_obs};        \
247 	STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask,                                     \
248 				_CONCAT(_CONCAT(_chan, _ZBUS_OBSERVATION_PREFIX(UTIL_INC(_idx))),  \
249 					_mask)) = {.enabled = false};
250 
251 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
252 #define _ZBUS_RUNTIME_OBSERVERS(_name)      .observers = &(_CONCAT(_observers_, _name)),
253 #define _ZBUS_RUNTIME_OBSERVERS_DECL(_name) static sys_slist_t _CONCAT(_observers_, _name);
254 #else
255 #define _ZBUS_RUNTIME_OBSERVERS(_name)
256 #define _ZBUS_RUNTIME_OBSERVERS_DECL(_name)
257 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
258 
259 /** @endcond */
260 
261 /* clang-format off */
262 /**
263  * @brief Add a static channel observervation.
264  *
265  * This macro initializes a channel observation by receiving the
266  * channel and the observer.
267  *
268  * @param _chan Channel instance.
269  * @param _obs Observer instance.
270  * @param _masked Observation state.
271  * @param _prio Observer notification sequence priority.
272  */
273 #define ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, _masked, _prio)                                   \
274 	const STRUCT_SECTION_ITERABLE(zbus_channel_observation,                                    \
275 		_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs))) = {                             \
276 			.chan = &_chan,                                                            \
277 			.obs = &_obs,                                                              \
278 	};                                                                                         \
279 	STRUCT_SECTION_ITERABLE(zbus_channel_observation_mask,                                     \
280 				_CONCAT(_CONCAT(_CONCAT(_chan, zz), _CONCAT(_prio, _obs)),         \
281 					_mask)) = {.enabled = _masked}
282 /* clang-format on */
283 
284 /**
285  * @brief Add a static channel observervation.
286  *
287  * This macro initializes a channel observation by receiving the
288  * channel and the observer.
289  *
290  * @param _chan Channel instance.
291  * @param _obs Observer instance.
292  * @param _prio Observer notification sequence priority.
293  */
294 #define ZBUS_CHAN_ADD_OBS(_chan, _obs, _prio) ZBUS_CHAN_ADD_OBS_WITH_MASK(_chan, _obs, false, _prio)
295 
296 /**
297  * @def ZBUS_OBS_DECLARE
298  * This macro list the observers to be used in a file. Internally, it declares the observers with
299  * the extern statement. Note it is only necessary when the observers are declared outside the file.
300  */
301 #define ZBUS_OBS_DECLARE(...) FOR_EACH_NONEMPTY_TERM(_ZBUS_OBS_EXTERN, (;), __VA_ARGS__)
302 
303 /**
304  * @def ZBUS_CHAN_DECLARE
305  * This macro list the channels to be used in a file. Internally, it declares the channels with the
306  * extern statement. Note it is only necessary when the channels are declared outside the file.
307  */
308 #define ZBUS_CHAN_DECLARE(...) FOR_EACH(_ZBUS_CHAN_EXTERN, (;), __VA_ARGS__)
309 
310 /**
311  * @def ZBUS_OBSERVERS_EMPTY
312  * This macro indicates the channel has no observers.
313  */
314 #define ZBUS_OBSERVERS_EMPTY
315 
316 /**
317  * @def ZBUS_OBSERVERS
318  * This macro indicates the channel has listed observers. Note the sequence of observer notification
319  * will follow the same as listed.
320  */
321 #define ZBUS_OBSERVERS(...) __VA_ARGS__
322 
323 /* clang-format off */
324 /**
325  * @brief Zbus channel definition.
326  *
327  * This macro defines a channel.
328  *
329  * @param _name The channel's name.
330  * @param _type The Message type. It must be a struct or union.
331  * @param _validator The validator function.
332  * @param _user_data A pointer to the user data.
333  *
334  * @see struct zbus_channel
335  * @param _observers The observers list. The sequence indicates the priority of the observer. The
336  * first the highest priority.
337  * @param _init_val The message initialization.
338  */
339 #define ZBUS_CHAN_DEFINE(_name, _type, _validator, _user_data, _observers, _init_val)     \
340 	static _type _CONCAT(_zbus_message_, _name) = _init_val;                          \
341 	static struct zbus_channel_data _CONCAT(_zbus_chan_data_, _name) = {              \
342 		.observers_start_idx = -1,                                                \
343 		.observers_end_idx = -1,                                                  \
344 		.sem = Z_SEM_INITIALIZER(_CONCAT(_zbus_chan_data_, _name).sem, 1, 1),     \
345 		IF_ENABLED(CONFIG_ZBUS_RUNTIME_OBSERVERS, (                               \
346 			.observers = SYS_SLIST_STATIC_INIT(                               \
347 				&_CONCAT(_zbus_chan_data_, _name).observers),             \
348 		))                                                                        \
349 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                                  \
350 			.highest_observer_priority = ZBUS_MIN_THREAD_PRIORITY,            \
351 		))                                                                        \
352 	};                                                                                \
353 	static K_MUTEX_DEFINE(_CONCAT(_zbus_mutex_, _name));                              \
354 	_ZBUS_CPP_EXTERN const STRUCT_SECTION_ITERABLE(zbus_channel, _name) = {           \
355 		ZBUS_CHANNEL_NAME_INIT(_name) /* Maybe removed */                         \
356 		.message = &_CONCAT(_zbus_message_, _name),                               \
357 		.message_size = sizeof(_type),                                            \
358 		.user_data = _user_data,                                                  \
359 		.validator = _validator,                                                  \
360 		.data = &_CONCAT(_zbus_chan_data_, _name),                                \
361 		IF_ENABLED(ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION, (                  \
362 			.msg_subscriber_pool = &_zbus_msg_subscribers_pool,               \
363 		))                                                                        \
364 	};                                                                                \
365 	/* Extern declaration of observers */                                             \
366 	ZBUS_OBS_DECLARE(_observers);                                                     \
367 	/* Create all channel observations from observers list */                         \
368 	FOR_EACH_FIXED_ARG_NONEMPTY_TERM(_ZBUS_CHAN_OBSERVATION, (;), _name, _observers)
369 /* clang-format on */
370 
371 /**
372  * @brief Initialize a message.
373  *
374  * This macro initializes a message by passing the values to initialize the message struct
375  * or union.
376  *
377  * @param[in] _val Variadic with the initial values. ``ZBUS_INIT(0)`` means ``{0}``, as
378  * ZBUS_INIT(.a=10, .b=30) means ``{.a=10, .b=30}``.
379  */
380 #define ZBUS_MSG_INIT(_val, ...)                                                                   \
381 	{                                                                                          \
382 		_val, ##__VA_ARGS__                                                                \
383 	}
384 
385 /* clang-format off */
386 /**
387  * @brief Define and initialize a subscriber.
388  *
389  * This macro defines an observer of subscriber type. It defines a message queue where the
390  * subscriber will receive the notification asynchronously, and initialize the ``struct
391  * zbus_observer`` defining the subscriber.
392  *
393  * @param[in] _name The subscriber's name.
394  * @param[in] _queue_size The notification queue's size.
395  * @param[in] _enable The subscriber initial enable state.
396  */
397 #define ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, _enable)       \
398 	K_MSGQ_DEFINE(_zbus_observer_queue_##_name,                           \
399 		      sizeof(const struct zbus_channel *),                    \
400 		      _queue_size, sizeof(const struct zbus_channel *)        \
401 	);                                                                    \
402 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {  \
403 		.enabled = _enable,                                           \
404 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                      \
405 			.priority = ZBUS_MIN_THREAD_PRIORITY,                 \
406 		))                                                            \
407 	};                                                                    \
408 	STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {                     \
409 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */               \
410 		.type = ZBUS_OBSERVER_SUBSCRIBER_TYPE,                        \
411 		.data = &_CONCAT(_zbus_obs_data_, _name),                     \
412 		.queue = &_zbus_observer_queue_##_name,                       \
413 	}
414 /* clang-format on */
415 
416 /**
417  * @brief Define and initialize a subscriber.
418  *
419  * This macro defines an observer of subscriber type. It defines a message queue where the
420  * subscriber will receive the notification asynchronously, and initialize the ``struct
421  * zbus_observer`` defining the subscriber. The subscribers are defined in the enabled
422  * state with this macro.
423  *
424  * @param[in] _name The subscriber's name.
425  * @param[in] _queue_size The notification queue's size.
426  */
427 #define ZBUS_SUBSCRIBER_DEFINE(_name, _queue_size)                                                 \
428 	ZBUS_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _queue_size, true)
429 
430 /* clang-format off */
431 /**
432  * @brief Define and initialize a listener.
433  *
434  * This macro defines an observer of listener type. This macro establishes the callback where the
435  * listener will be notified synchronously, and initialize the ``struct zbus_observer`` defining the
436  * listener.
437  *
438  * @param[in] _name The listener's name.
439  * @param[in] _cb The callback function.
440  * @param[in] _enable The listener initial enable state.
441  */
442 #define ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, _enable)                                      \
443 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {                       \
444 		.enabled = _enable,                                                                \
445 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                                           \
446 			.priority = ZBUS_MIN_THREAD_PRIORITY,                                      \
447 		))                                                                                 \
448 	};                                                                                         \
449 	STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {                                          \
450 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */                                    \
451 		.type = ZBUS_OBSERVER_LISTENER_TYPE,                                               \
452 		.data = &_CONCAT(_zbus_obs_data_, _name),                                          \
453 		.callback = (_cb)                                                                  \
454 	}
455 /* clang-format on */
456 
457 /**
458  * @brief Define and initialize a listener.
459  *
460  * This macro defines an observer of listener type. This macro establishes the callback where the
461  * listener will be notified synchronously and initialize the ``struct zbus_observer`` defining the
462  * listener. The listeners are defined in the enabled state with this macro.
463  *
464  * @param[in] _name The listener's name.
465  * @param[in] _cb The callback function.
466  */
467 #define ZBUS_LISTENER_DEFINE(_name, _cb) ZBUS_LISTENER_DEFINE_WITH_ENABLE(_name, _cb, true)
468 
469 /* clang-format off */
470 /**
471  * @brief Define and initialize a message subscriber.
472  *
473  * This macro defines an observer of @ref ZBUS_OBSERVER_SUBSCRIBER_TYPE type. It defines a FIFO
474  * where the subscriber will receive the message asynchronously and initialize the @ref
475  * zbus_observer defining the subscriber.
476  *
477  * @param[in] _name The subscriber's name.
478  * @param[in] _enable The subscriber's initial state.
479  */
480 #define ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, _enable)                \
481 	static K_FIFO_DEFINE(_zbus_observer_fifo_##_name);                    \
482 	static struct zbus_observer_data _CONCAT(_zbus_obs_data_, _name) = {  \
483 		.enabled = _enable,                                           \
484 		IF_ENABLED(CONFIG_ZBUS_PRIORITY_BOOST, (                      \
485 			.priority = ZBUS_MIN_THREAD_PRIORITY,                 \
486 		))                                                            \
487 	};                                                                    \
488 	STRUCT_SECTION_ITERABLE(zbus_observer, _name) = {                     \
489 		ZBUS_OBSERVER_NAME_INIT(_name) /* Name field */               \
490 		.type = ZBUS_OBSERVER_MSG_SUBSCRIBER_TYPE,                    \
491 		.data = &_CONCAT(_zbus_obs_data_, _name),                     \
492 		.message_fifo = &_zbus_observer_fifo_##_name,                 \
493 	}
494 /* clang-format on */
495 
496 /**
497  * @brief Define and initialize an enabled message subscriber.
498  *
499  * This macro defines an observer of message subscriber type. It defines a FIFO where the
500  * subscriber will receive the message asynchronously and initialize the @ref
501  * zbus_observer defining the subscriber. The message subscribers are defined in the enabled state
502  * with this macro.
503 
504  *
505  * @param[in] _name The subscriber's name.
506  */
507 #define ZBUS_MSG_SUBSCRIBER_DEFINE(_name) ZBUS_MSG_SUBSCRIBER_DEFINE_WITH_ENABLE(_name, true)
508 /**
509  *
510  * @brief Publish to a channel
511  *
512  * This routine publishes a message to a channel.
513  *
514  * @param chan The channel's reference.
515  * @param msg Reference to the message where the publish function copies the channel's
516  * message data from.
517  * @param timeout Waiting period to publish the channel,
518  *                or one of the special values K_NO_WAIT and K_FOREVER.
519  *
520  * @retval 0 Channel published.
521  * @retval -ENOMSG The message is invalid based on the validator function or some of the
522  * observers could not receive the notification.
523  * @retval -EBUSY The channel is busy.
524  * @retval -EAGAIN Waiting period timed out.
525  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
526  * observer, or the function context is invalid (inside an ISR). The function only returns this
527  * value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
528  */
529 int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t timeout);
530 
531 /**
532  * @brief Read a channel
533  *
534  * This routine reads a message from a channel.
535  *
536  * @param[in] chan The channel's reference.
537  * @param[out] msg Reference to the message where the read function copies the channel's
538  * message data to.
539  * @param[in] timeout Waiting period to read the channel,
540  *                or one of the special values K_NO_WAIT and K_FOREVER.
541  *
542  * @retval 0 Channel read.
543  * @retval -EBUSY The channel is busy.
544  * @retval -EAGAIN Waiting period timed out.
545  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
546  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
547  */
548 int zbus_chan_read(const struct zbus_channel *chan, void *msg, k_timeout_t timeout);
549 
550 /**
551  * @brief Claim a channel
552  *
553  * This routine claims a channel. During the claiming period the channel is blocked for publishing,
554  * reading, notifying or claiming again. Finishing is the only available action.
555  *
556  * @warning After calling this routine, the channel cannot be used by other
557  * thread until the zbus_chan_finish routine is performed.
558  *
559  * @warning This routine should only be called once before a zbus_chan_finish.
560  *
561  * @param[in] chan The channel's reference.
562  * @param[in] timeout Waiting period to claim the channel,
563  *                or one of the special values K_NO_WAIT and K_FOREVER.
564  *
565  * @retval 0 Channel claimed.
566  * @retval -EBUSY The channel is busy.
567  * @retval -EAGAIN Waiting period timed out.
568  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
569  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
570  */
571 int zbus_chan_claim(const struct zbus_channel *chan, k_timeout_t timeout);
572 
573 /**
574  * @brief Finish a channel claim.
575  *
576  * This routine finishes a channel claim. After calling this routine with success, the channel will
577  * be able to be used by other thread.
578  *
579  * @warning This routine must only be used after a zbus_chan_claim.
580  *
581  * @param chan The channel's reference.
582  *
583  * @retval 0 Channel finished.
584  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
585  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
586  */
587 int zbus_chan_finish(const struct zbus_channel *chan);
588 
589 /**
590  * @brief Force a channel notification.
591  *
592  * This routine forces the event dispatcher to notify the channel's observers even if the message
593  * has no changes. Note this function could be useful after claiming/finishing actions.
594  *
595  * @param chan The channel's reference.
596  * @param timeout Waiting period to notify the channel,
597  *                or one of the special values K_NO_WAIT and K_FOREVER.
598  *
599  * @retval 0 Channel notified.
600  * @retval -EBUSY The channel's semaphore returned without waiting.
601  * @retval -EAGAIN Timeout to take the channel's semaphore.
602  * @retval -ENOMEM There is not more buffer on the messgage buffers pool.
603  * @retval -EFAULT A parameter is incorrect, the notification could not be sent to one or more
604  * observer, or the function context is invalid (inside an ISR). The function only returns this
605  * value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
606  */
607 int zbus_chan_notify(const struct zbus_channel *chan, k_timeout_t timeout);
608 
609 #if defined(CONFIG_ZBUS_CHANNEL_NAME) || defined(__DOXYGEN__)
610 
611 /**
612  * @brief Get the channel's name.
613  *
614  * This routine returns the channel's name reference.
615  *
616  * @param chan The channel's reference.
617  *
618  * @return Channel's name reference.
619  */
zbus_chan_name(const struct zbus_channel * chan)620 static inline const char *zbus_chan_name(const struct zbus_channel *chan)
621 {
622 	__ASSERT(chan != NULL, "chan is required");
623 
624 	return chan->name;
625 }
626 
627 #endif
628 
629 /**
630  * @brief Get the reference for a channel message directly.
631  *
632  * This routine returns the reference of a channel message.
633  *
634  * @warning This function must only be used directly for already locked channels. This
635  * can be done inside a listener for the receiving channel or after claim a channel.
636  *
637  * @param chan The channel's reference.
638  *
639  * @return Channel's message reference.
640  */
zbus_chan_msg(const struct zbus_channel * chan)641 static inline void *zbus_chan_msg(const struct zbus_channel *chan)
642 {
643 	__ASSERT(chan != NULL, "chan is required");
644 
645 	return chan->message;
646 }
647 
648 /**
649  * @brief Get a constant reference for a channel message directly.
650  *
651  * This routine returns a constant reference of a channel message. This should be used
652  * inside listeners to access the message directly. In this way zbus prevents the listener of
653  * changing the notifying channel's message during the notification process.
654  *
655  * @warning This function must only be used directly for already locked channels. This
656  * can be done inside a listener for the receiving channel or after claim a channel.
657  *
658  * @param chan The channel's constant reference.
659  *
660  * @return A constant channel's message reference.
661  */
zbus_chan_const_msg(const struct zbus_channel * chan)662 static inline const void *zbus_chan_const_msg(const struct zbus_channel *chan)
663 {
664 	__ASSERT(chan != NULL, "chan is required");
665 
666 	return chan->message;
667 }
668 
669 /**
670  * @brief Get the channel's message size.
671  *
672  * This routine returns the channel's message size.
673  *
674  * @param chan The channel's reference.
675  *
676  * @return Channel's message size.
677  */
zbus_chan_msg_size(const struct zbus_channel * chan)678 static inline uint16_t zbus_chan_msg_size(const struct zbus_channel *chan)
679 {
680 	__ASSERT(chan != NULL, "chan is required");
681 
682 	return chan->message_size;
683 }
684 
685 /**
686  * @brief Get the channel's user data.
687  *
688  * This routine returns the channel's user data.
689  *
690  * @param chan The channel's reference.
691  *
692  * @return Channel's user data.
693  */
zbus_chan_user_data(const struct zbus_channel * chan)694 static inline void *zbus_chan_user_data(const struct zbus_channel *chan)
695 {
696 	__ASSERT(chan != NULL, "chan is required");
697 
698 	return chan->user_data;
699 }
700 
701 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION) || defined(__DOXYGEN__)
702 
703 /**
704  * @brief Set the channel's msg subscriber `net_buf` pool.
705  *
706  * @param chan The channel's reference.
707  * @param pool The reference to the `net_buf` memory pool.
708  */
zbus_chan_set_msg_sub_pool(const struct zbus_channel * chan,struct net_buf_pool * pool)709 static inline void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan,
710 					      struct net_buf_pool *pool)
711 {
712 	__ASSERT(chan != NULL, "chan is required");
713 	__ASSERT(pool != NULL, "pool is required");
714 
715 	chan->data->msg_subscriber_pool = pool;
716 }
717 
718 #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */
719 
720 #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__)
721 
722 /**
723  * @brief Add an observer to a channel.
724  *
725  * This routine adds an observer to the channel.
726  *
727  * @param chan The channel's reference.
728  * @param obs The observer's reference to be added.
729  * @param timeout Waiting period to add an observer,
730  *                or one of the special values K_NO_WAIT and K_FOREVER.
731  *
732  * @retval 0 Observer added to the channel.
733  * @retval -EALREADY The observer is already present in the channel's runtime observers list.
734  * @retval -ENOMEM Returned without waiting.
735  * @retval -EAGAIN Waiting period timed out.
736  * @retval -EINVAL Some parameter is invalid.
737  */
738 int zbus_chan_add_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
739 		      k_timeout_t timeout);
740 
741 /**
742  * @brief Remove an observer from a channel.
743  *
744  * This routine removes an observer to the channel.
745  *
746  * @param chan The channel's reference.
747  * @param obs The observer's reference to be removed.
748  * @param timeout Waiting period to remove an observer,
749  *                or one of the special values K_NO_WAIT and K_FOREVER.
750  *
751  * @retval 0 Observer removed to the channel.
752  * @retval -EINVAL Invalid data supplied.
753  * @retval -EBUSY Returned without waiting.
754  * @retval -EAGAIN Waiting period timed out.
755  * @retval -ENODATA no observer found in channel's runtime observer list.
756  * @retval -ENOMEM Returned without waiting.
757  */
758 int zbus_chan_rm_obs(const struct zbus_channel *chan, const struct zbus_observer *obs,
759 		     k_timeout_t timeout);
760 
761 /** @cond INTERNAL_HIDDEN */
762 
763 struct zbus_observer_node {
764 	sys_snode_t node;
765 	const struct zbus_observer *obs;
766 };
767 
768 /** @endcond */
769 
770 #endif /* CONFIG_ZBUS_RUNTIME_OBSERVERS */
771 
772 /**
773  * @brief Change the observer state.
774  *
775  * This routine changes the observer state. A channel when disabled will not receive
776  * notifications from the event dispatcher.
777  *
778  * @param[in] obs The observer's reference.
779  * @param[in] enabled State to be. When false the observer stops to receive notifications.
780  *
781  * @retval 0 Observer set enable.
782  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
783  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
784  */
785 int zbus_obs_set_enable(struct zbus_observer *obs, bool enabled);
786 
787 /**
788  * @brief Get the observer state.
789  *
790  * This routine retrieves the observer state.
791  *
792  * @param[in] obs The observer's reference.
793  * @param[out] enable The boolean output's reference.
794  *
795  * @return Observer state.
796  */
zbus_obs_is_enabled(struct zbus_observer * obs,bool * enable)797 static inline int zbus_obs_is_enabled(struct zbus_observer *obs, bool *enable)
798 {
799 	_ZBUS_ASSERT(obs != NULL, "obs is required");
800 	_ZBUS_ASSERT(enable != NULL, "enable is required");
801 
802 	*enable = obs->data->enabled;
803 
804 	return 0;
805 }
806 
807 /**
808  * @brief Mask notifications from a channel to an observer.
809  *
810  * The observer can mask notifications from a specific observing channel by calling this function.
811  *
812  * @param obs The observer's reference to be added.
813  * @param chan The channel's reference.
814  * @param masked The mask state. When the mask is true, the observer will not receive notifications
815  * from the channel.
816  *
817  * @retval 0 Channel notifications masked to the observer.
818  * @retval -ESRCH No observation found for the related pair chan/obs.
819  * @retval -EINVAL Some parameter is invalid.
820  */
821 int zbus_obs_set_chan_notification_mask(const struct zbus_observer *obs,
822 					const struct zbus_channel *chan, bool masked);
823 
824 /**
825  * @brief Get the notifications masking state from a channel to an observer.
826  *
827  * @param obs The observer's reference to be added.
828  * @param chan The channel's reference.
829  * @param[out] masked The mask state. When the mask is true, the observer will not receive
830  * notifications from the channel.
831  *
832  * @retval 0 Retrieved the masked state.
833  * @retval -ESRCH No observation found for the related pair chan/obs.
834  * @retval -EINVAL Some parameter is invalid.
835  */
836 int zbus_obs_is_chan_notification_masked(const struct zbus_observer *obs,
837 					 const struct zbus_channel *chan, bool *masked);
838 
839 #if defined(CONFIG_ZBUS_OBSERVER_NAME) || defined(__DOXYGEN__)
840 
841 /**
842  * @brief Get the observer's name.
843  *
844  * This routine returns the observer's name reference.
845  *
846  * @param obs The observer's reference.
847  *
848  * @return The observer's name reference.
849  */
zbus_obs_name(const struct zbus_observer * obs)850 static inline const char *zbus_obs_name(const struct zbus_observer *obs)
851 {
852 	__ASSERT(obs != NULL, "obs is required");
853 
854 	return obs->name;
855 }
856 
857 #endif
858 
859 #if defined(CONFIG_ZBUS_PRIORITY_BOOST) || defined(__DOXYGEN__)
860 
861 /**
862  * @brief Set the observer thread priority by attaching it to a thread.
863  *
864  * @param[in] obs The observer's reference.
865  *
866  * @retval 0 Observer detached from the thread.
867  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
868  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
869  */
870 int zbus_obs_attach_to_thread(const struct zbus_observer *obs);
871 
872 /**
873  * @brief Clear the observer thread priority by detaching it from a thread.
874  *
875  * @param[in] obs The observer's reference.
876  *
877  * @retval 0 Observer detached from the thread.
878  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
879  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
880  */
881 int zbus_obs_detach_from_thread(const struct zbus_observer *obs);
882 
883 #endif /* CONFIG_ZBUS_PRIORITY_BOOST */
884 
885 /**
886  * @brief Wait for a channel notification.
887  *
888  * This routine makes the subscriber to wait a notification. The notification comes as a channel
889  * reference.
890  *
891  * @param[in] sub The subscriber's reference.
892  * @param[out] chan The notification channel's reference.
893  * @param[in] timeout Waiting period for a notification arrival,
894  *                or one of the special values K_NO_WAIT and K_FOREVER.
895  *
896  * @retval 0 Notification received.
897  * @retval -ENOMSG Returned without waiting.
898  * @retval -EAGAIN Waiting period timed out.
899  * @retval -EINVAL The observer is not a subscriber.
900  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
901  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
902  */
903 int zbus_sub_wait(const struct zbus_observer *sub, const struct zbus_channel **chan,
904 		  k_timeout_t timeout);
905 
906 #if defined(CONFIG_ZBUS_MSG_SUBSCRIBER) || defined(__DOXYGEN__)
907 
908 /**
909  * @brief Wait for a channel message.
910  *
911  * This routine makes the subscriber wait for the new message in case of channel publication.
912  *
913  * @param[in] sub The subscriber's reference.
914  * @param[out] chan The notification channel's reference.
915  * @param[out] msg A reference to a copy of the published message.
916  * @param[in] timeout Waiting period for a notification arrival,
917  *                or one of the special values, K_NO_WAIT and K_FOREVER.
918  *
919  * @retval 0 Message received.
920  * @retval -EINVAL The observer is not a subscriber.
921  * @retval -ENOMSG Could not retrieve the net_buf from the subscriber FIFO.
922  * @retval -EILSEQ Received an invalid channel reference.
923  * @retval -EFAULT A parameter is incorrect, or the function context is invalid (inside an ISR). The
924  * function only returns this value when the @kconfig{CONFIG_ZBUS_ASSERT_MOCK} is enabled.
925  */
926 int zbus_sub_wait_msg(const struct zbus_observer *sub, const struct zbus_channel **chan, void *msg,
927 		      k_timeout_t timeout);
928 
929 #endif /* CONFIG_ZBUS_MSG_SUBSCRIBER */
930 
931 /**
932  *
933  * @brief Iterate over channels.
934  *
935  * Enables the developer to iterate over the channels giving to this function an
936  * iterator_func which is called for each channel. If the iterator_func returns false all
937  * the iteration stops.
938  *
939  * @param[in] iterator_func The function that will be execute on each iteration.
940  *
941  * @retval true Iterator executed for all channels.
942  * @retval false Iterator could not be executed. Some iterate returned false.
943  */
944 bool zbus_iterate_over_channels(bool (*iterator_func)(const struct zbus_channel *chan));
945 /**
946  *
947  * @brief Iterate over channels with user data.
948  *
949  * Enables the developer to iterate over the channels giving to this function an
950  * iterator_func which is called for each channel. If the iterator_func returns false all
951  * the iteration stops.
952  *
953  * @param[in] iterator_func The function that will be execute on each iteration.
954  * @param[in] user_data The user data that can be passed in the function.
955  *
956  * @retval true Iterator executed for all channels.
957  * @retval false Iterator could not be executed. Some iterate returned false.
958  */
959 bool zbus_iterate_over_channels_with_user_data(
960 	bool (*iterator_func)(const struct zbus_channel *chan, void *user_data), void *user_data);
961 
962 /**
963  *
964  * @brief Iterate over observers.
965  *
966  * Enables the developer to iterate over the observers giving to this function an
967  * iterator_func which is called for each observer. If the iterator_func returns false all
968  * the iteration stops.
969  *
970  * @param[in] iterator_func The function that will be execute on each iteration.
971  *
972  * @retval true Iterator executed for all channels.
973  * @retval false Iterator could not be executed. Some iterate returned false.
974  */
975 bool zbus_iterate_over_observers(bool (*iterator_func)(const struct zbus_observer *obs));
976 /**
977  *
978  * @brief Iterate over observers with user data.
979  *
980  * Enables the developer to iterate over the observers giving to this function an
981  * iterator_func which is called for each observer. If the iterator_func returns false all
982  * the iteration stops.
983  *
984  * @param[in] iterator_func The function that will be execute on each iteration.
985  * @param[in] user_data The user data that can be passed in the function.
986  *
987  * @retval true Iterator executed for all channels.
988  * @retval false Iterator could not be executed. Some iterate returned false.
989  */
990 bool zbus_iterate_over_observers_with_user_data(
991 	bool (*iterator_func)(const struct zbus_observer *obs, void *user_data), void *user_data);
992 
993 /**
994  * @}
995  */
996 
997 #ifdef __cplusplus
998 }
999 #endif
1000 
1001 #endif /* ZEPHYR_INCLUDE_ZBUS_H_ */
1002