Skip to content

Commit b01e41c

Browse files
Jordan Yatesnashif
authored andcommitted
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 <[email protected]>
1 parent 0c6588f commit b01e41c

File tree

2 files changed

+103
-7
lines changed

2 files changed

+103
-7
lines changed

include/device.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,47 @@ device_required_handles_get(const struct device *dev,
487487
return rv;
488488
}
489489

490+
/**
491+
* @brief Get the set of handles that this device supports.
492+
*
493+
* The set of supported devices is inferred from devicetree, and does not
494+
* include any software constructs that may depend on the device.
495+
*
496+
* @param dev the device for which supports are desired.
497+
*
498+
* @param count pointer to a place to store the number of devices provided at
499+
* the returned pointer. The value is not set if the call returns a null
500+
* pointer. The value may be set to zero.
501+
*
502+
* @return a pointer to a sequence of @p *count device handles, or a null
503+
* pointer if @p dh does not provide dependency information.
504+
*/
505+
static inline const device_handle_t *
506+
device_supported_handles_get(const struct device *dev,
507+
size_t *count)
508+
{
509+
const device_handle_t *rv = dev->handles;
510+
size_t region = 0;
511+
size_t i = 0;
512+
513+
if (rv != NULL) {
514+
/* Fast forward to supporting devices */
515+
while (region != 2) {
516+
if (*rv == DEVICE_HANDLE_SEP) {
517+
region++;
518+
}
519+
rv++;
520+
}
521+
/* Count supporting devices */
522+
while (rv[i] != DEVICE_HANDLE_ENDS) {
523+
++i;
524+
}
525+
*count = i;
526+
}
527+
528+
return rv;
529+
}
530+
490531
/**
491532
* @brief Visit every device that @p dev directly requires.
492533
*
@@ -524,6 +565,42 @@ int device_required_foreach(const struct device *dev,
524565
device_visitor_callback_t visitor_cb,
525566
void *context);
526567

568+
/**
569+
* @brief Visit every device that @p dev directly supports.
570+
*
571+
* Zephyr maintains information about which devices are directly supported by
572+
* another device; for example an I2C controller will support an I2C-based
573+
* sensor driver. Supported devices can derive from statically-defined
574+
* devicetree relationships.
575+
*
576+
* This API supports operating on the set of supported devices. Example uses
577+
* include iterating over the devices connected to a regulator when it is
578+
* powered on.
579+
*
580+
* There is no guarantee on the order in which required devices are visited.
581+
*
582+
* If the @p visitor function returns a negative value iteration is halted,
583+
* and the returned value from the visitor is returned from this function.
584+
*
585+
* @note This API is not available to unprivileged threads.
586+
*
587+
* @param dev a device of interest. The devices that this device supports
588+
* will be used as the set of devices to visit. This parameter must not be
589+
* null.
590+
*
591+
* @param visitor_cb the function that should be invoked on each device in the
592+
* support set. This parameter must not be null.
593+
*
594+
* @param context state that is passed through to the visitor function. This
595+
* parameter may be null if @p visitor tolerates a null @p context.
596+
*
597+
* @return The number of devices that were visited if all visits succeed, or
598+
* the negative value returned from the first visit that did not succeed.
599+
*/
600+
int device_supported_foreach(const struct device *dev,
601+
device_visitor_callback_t visitor_cb,
602+
void *context);
603+
527604
/**
528605
* @brief Retrieve the device structure for a driver by name
529606
*

kernel/device.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,11 @@ bool z_device_ready(const struct device *dev)
176176
return dev->state->initialized && (dev->state->init_res == 0U);
177177
}
178178

179-
int device_required_foreach(const struct device *dev,
180-
device_visitor_callback_t visitor_cb,
181-
void *context)
179+
static int device_visitor(const device_handle_t *handles,
180+
size_t handle_count,
181+
device_visitor_callback_t visitor_cb,
182+
void *context)
182183
{
183-
size_t handle_count = 0;
184-
const device_handle_t *handles =
185-
device_required_handles_get(dev, &handle_count);
186-
187184
/* Iterate over fixed devices */
188185
for (size_t i = 0; i < handle_count; ++i) {
189186
device_handle_t dh = handles[i];
@@ -197,3 +194,25 @@ int device_required_foreach(const struct device *dev,
197194

198195
return handle_count;
199196
}
197+
198+
int device_required_foreach(const struct device *dev,
199+
device_visitor_callback_t visitor_cb,
200+
void *context)
201+
{
202+
size_t handle_count = 0;
203+
const device_handle_t *handles =
204+
device_required_handles_get(dev, &handle_count);
205+
206+
return device_visitor(handles, handle_count, visitor_cb, context);
207+
}
208+
209+
int device_supported_foreach(const struct device *dev,
210+
device_visitor_callback_t visitor_cb,
211+
void *context)
212+
{
213+
size_t handle_count = 0;
214+
const device_handle_t *handles =
215+
device_supported_handles_get(dev, &handle_count);
216+
217+
return device_visitor(handles, handle_count, visitor_cb, context);
218+
}

0 commit comments

Comments
 (0)