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