blob: 0faa35e72193815af51dcb4d8452d57ac3d4e704 [file] [log] [blame] [edit]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_DRIVER_DEVICETREE_MANAGER_MANAGER_H_
#define LIB_DRIVER_DEVICETREE_MANAGER_MANAGER_H_
#include <fidl/fuchsia.driver.framework/cpp/fidl.h>
#include <fidl/fuchsia.hardware.platform.bus/cpp/driver/fidl.h>
#include <lib/devicetree/devicetree.h>
#include <lib/driver/incoming/cpp/namespace.h>
#include <lib/stdcompat/span.h>
#include <lib/zx/result.h>
#include <unordered_map>
#include <vector>
#include "lib/driver/devicetree/manager/visitor.h"
namespace fdf_devicetree {
class Manager final : public NodeManager {
public:
static zx::result<Manager> CreateFromNamespace(fdf::Namespace& ns);
// Create a new device tree manager using the given FDT blob.
explicit Manager(std::vector<uint8_t> fdt_blob)
: fdt_blob_(std::move(fdt_blob)),
tree_(devicetree::ByteView{fdt_blob_.data(), fdt_blob_.size()}) {}
// This method does the following things -
// * Does the initial walk of the tree and discovers devices/nodes.
// * Calls |visitor.Visit()| for each node in the tree.
// If |visitor.Visit()| returns something that's not `zx::ok()`, then this
// will stop walking and return the error code.
//
// This method can be called with the |DefaultVisitors| or with a collection
// of visitors of user's choice.
// Example:
// DefaultVisitors<> visitors;
// auto result = manager.Walk(visitors)
//
// This needs to be called before |PublishDevices|.
zx::result<> Walk(Visitor& visitor);
// Publish the discovered devices.
// The devices maybe added as a platform device using |pbus_client| if it contains any platform
// resources, or it maybe added as a child of the board driver using |fdf_node|, or it maybe added
// as a composite of multiple devices if it references other nodes.
zx::result<> PublishDevices(
fdf::WireSyncClient<fuchsia_hardware_platform_bus::PlatformBus>& pbus_client,
fidl::ClientEnd<fuchsia_driver_framework::CompositeNodeManager> mgr,
fidl::SyncClient<fuchsia_driver_framework::Node>& fdf_node);
const std::vector<std::unique_ptr<Node>>& nodes() { return nodes_publish_order_; }
// Returns node with phandle |id|.
zx::result<ReferenceNode> GetReferenceNode(Phandle id) override;
// Returns index of the node in the publish list.
uint32_t GetPublishIndex(uint32_t node_id) override;
// Moves the node with |node_id| to the |new_index| in the publish list.
zx::result<> ChangePublishOrder(uint32_t node_id, uint32_t new_index) override;
// Find a node by its name.
std::optional<Node*> FindNode(std::string_view name);
private:
std::vector<uint8_t> fdt_blob_;
devicetree::Devicetree tree_;
// List of nodes, in the order that they were seen in the tree.
std::vector<std::unique_ptr<Node>> nodes_publish_order_;
// Nodes by phandle. Note that not every node in the tree has a phandle.
std::unordered_map<Phandle, Node*> nodes_by_phandle_;
// Nodes by path.
std::unordered_map<std::string, Node*> nodes_by_path_;
uint32_t node_id_ = 0;
};
} // namespace fdf_devicetree
#endif // LIB_DRIVER_DEVICETREE_MANAGER_MANAGER_H_