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