From 08bc0cc9ca3f16c62ea019712c5102fc9a136c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Sun, 15 Mar 2020 19:53:06 +0100 Subject: [PATCH] device_manager: add find_child_node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to find a node in the hierarchy. Change-Id: Iee858f21ce134569bf25fccbef9fe18ea8787e9d Reviewed-on: https://review.haiku-os.org/c/haiku/+/2419 Reviewed-by: Jérôme Duval --- headers/os/drivers/device_manager.h | 4 ++ .../kernel/device_manager/device_manager.cpp | 48 +++++++++++++++++++ 2 files changed, 52 insertions(+) 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 };