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