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