device: supported devices visitor API

Adds an API to query and visit supported devices. Follows the example
set by the required devices API.

Implements #37793.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
This commit is contained in:
Jordan Yates 2021-08-20 19:29:39 +10:00 committed by Carles Cufí
commit f515aa0cf0
2 changed files with 101 additions and 7 deletions

View file

@ -488,6 +488,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.
*
@ -525,6 +566,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
*

View file

@ -162,14 +162,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];
@ -183,3 +180,23 @@ 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);
}