Skip to content

Commit

Permalink
device: supported devices visitor API
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Jordan Yates authored and nashif committed Aug 25, 2021
1 parent 0c6588f commit b01e41c
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 7 deletions.
77 changes: 77 additions & 0 deletions include/device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -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
*
Expand Down
33 changes: 26 additions & 7 deletions kernel/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
}

0 comments on commit b01e41c

Please sign in to comment.