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