diff --git a/headers/os/drivers/device_manager.h b/headers/os/drivers/device_manager.h index a411d4708f..2fdccbf9b1 100644 --- a/headers/os/drivers/device_manager.h +++ b/headers/os/drivers/device_manager.h @@ -101,6 +101,10 @@ typedef struct device_manager_info { const void **_data, size_t *_size, bool recursive); status_t (*get_next_attr)(device_node *node, device_attr **_attr); + + status_t (*find_child_node)(device_node *parent, + const device_attr *attrs, device_node **node); + } device_manager_info; diff --git a/src/system/kernel/device_manager/device_manager.cpp b/src/system/kernel/device_manager/device_manager.cpp index 0e3bccea97..f057377b18 100644 --- a/src/system/kernel/device_manager/device_manager.cpp +++ b/src/system/kernel/device_manager/device_manager.cpp @@ -893,6 +893,53 @@ get_next_attr(device_node* node, device_attr** _attr) } +static status_t +find_child_node(device_node* parent, const device_attr* attributes, + device_node** _node, bool *_lastFound) +{ + RecursiveLocker _(sLock); + + NodeList::ConstIterator iterator = parent->Children().GetIterator(); + device_node* last = *_node; + + // find the next one that fits + while (iterator.HasNext()) { + device_node* node = iterator.Next(); + + if (!node->IsRegistered()) + continue; + + if (node == last) + *_lastFound = true; + else if (!node->CompareTo(attributes) && *_lastFound) { + if (last != NULL) + last->Release(); + + node->Acquire(); + *_node = node; + return B_OK; + } + if (find_child_node(node, attributes, _node, _lastFound) == B_OK) + return B_OK; + } + + return B_ENTRY_NOT_FOUND; +} + + +static status_t +find_child_node(device_node* parent, const device_attr* attributes, + device_node** _node) +{ + device_node* last = *_node; + bool lastFound = last == NULL; + status_t status = find_child_node(parent, attributes, _node, &lastFound); + if (status == B_ENTRY_NOT_FOUND && last != NULL && lastFound) + last->Release(); + return status; +} + + struct device_manager_info gDeviceManagerModule = { { B_DEVICE_MANAGER_MODULE_NAME, @@ -928,6 +975,7 @@ struct device_manager_info gDeviceManagerModule = { get_attr_string, get_attr_raw, get_next_attr, + find_child_node };