diff --git a/include/device.h b/include/device.h index 8a0d5c6a8ff2..9d862caac280 100644 --- a/include/device.h +++ b/include/device.h @@ -487,6 +487,47 @@ device_required_handles_get(const struct device *dev, return rv; } +/** + * @brief Get the set of handles that this device supports. + * + * The set of supported devices is inferred from devicetree, and does not + * include any software constructs that may depend on the device. + * + * @param dev the device for which supports are desired. + * + * @param count pointer to a place to store the number of devices provided at + * the returned pointer. The value is not set if the call returns a null + * pointer. The value may be set to zero. + * + * @return a pointer to a sequence of @p *count device handles, or a null + * pointer if @p dh does not provide dependency information. + */ +static inline const device_handle_t * +device_supported_handles_get(const struct device *dev, + size_t *count) +{ + const device_handle_t *rv = dev->handles; + size_t region = 0; + size_t i = 0; + + if (rv != NULL) { + /* Fast forward to supporting devices */ + while (region != 2) { + if (*rv == DEVICE_HANDLE_SEP) { + region++; + } + rv++; + } + /* Count supporting devices */ + while (rv[i] != DEVICE_HANDLE_ENDS) { + ++i; + } + *count = i; + } + + return rv; +} + /** * @brief Visit every device that @p dev directly requires. * @@ -524,6 +565,42 @@ int device_required_foreach(const struct device *dev, device_visitor_callback_t visitor_cb, void *context); +/** + * @brief Visit every device that @p dev directly supports. + * + * Zephyr maintains information about which devices are directly supported by + * another device; for example an I2C controller will support an I2C-based + * sensor driver. Supported devices can derive from statically-defined + * devicetree relationships. + * + * This API supports operating on the set of supported devices. Example uses + * include iterating over the devices connected to a regulator when it is + * powered on. + * + * There is no guarantee on the order in which required devices are visited. + * + * If the @p visitor function returns a negative value iteration is halted, + * and the returned value from the visitor is returned from this function. + * + * @note This API is not available to unprivileged threads. + * + * @param dev a device of interest. The devices that this device supports + * will be used as the set of devices to visit. This parameter must not be + * null. + * + * @param visitor_cb the function that should be invoked on each device in the + * support set. This parameter must not be null. + * + * @param context state that is passed through to the visitor function. This + * parameter may be null if @p visitor tolerates a null @p context. + * + * @return The number of devices that were visited if all visits succeed, or + * the negative value returned from the first visit that did not succeed. + */ +int device_supported_foreach(const struct device *dev, + device_visitor_callback_t visitor_cb, + void *context); + /** * @brief Retrieve the device structure for a driver by name * diff --git a/kernel/device.c b/kernel/device.c index f09dcf554842..3d7b23e8af8e 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -176,14 +176,11 @@ bool z_device_ready(const struct device *dev) return dev->state->initialized && (dev->state->init_res == 0U); } -int device_required_foreach(const struct device *dev, - device_visitor_callback_t visitor_cb, - void *context) +static int device_visitor(const device_handle_t *handles, + size_t handle_count, + device_visitor_callback_t visitor_cb, + void *context) { - size_t handle_count = 0; - const device_handle_t *handles = - device_required_handles_get(dev, &handle_count); - /* Iterate over fixed devices */ for (size_t i = 0; i < handle_count; ++i) { device_handle_t dh = handles[i]; @@ -197,3 +194,25 @@ int device_required_foreach(const struct device *dev, return handle_count; } + +int device_required_foreach(const struct device *dev, + device_visitor_callback_t visitor_cb, + void *context) +{ + size_t handle_count = 0; + const device_handle_t *handles = + device_required_handles_get(dev, &handle_count); + + return device_visitor(handles, handle_count, visitor_cb, context); +} + +int device_supported_foreach(const struct device *dev, + device_visitor_callback_t visitor_cb, + void *context) +{ + size_t handle_count = 0; + const device_handle_t *handles = + device_supported_handles_get(dev, &handle_count); + + return device_visitor(handles, handle_count, visitor_cb, context); +}