| // Copyright 2022 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 SRC_DEVICES_BIN_DRIVER_MANAGER_V2_COMPOSITE_ASSEMBLER_H_ |
| #define SRC_DEVICES_BIN_DRIVER_MANAGER_V2_COMPOSITE_ASSEMBLER_H_ |
| |
| #include <fidl/fuchsia.device.manager/cpp/fidl.h> |
| |
| #include "src/devices/bin/driver_manager/binding.h" |
| #include "src/devices/bin/driver_manager/v2/node.h" |
| |
| namespace dfv2 { |
| |
| fbl::Array<const zx_device_prop_t> NodeToProps(Node* node); |
| |
| // This class represents a single fragment of a composite device. It will |
| // match one node. |
| class CompositeDeviceFragment { |
| public: |
| static zx::status<CompositeDeviceFragment> Create( |
| fuchsia_device_manager::DeviceFragment fragment); |
| |
| // Try to bind the node against this fragment. This returns true if the node |
| // matches and the fragment is currently unbound. |
| bool BindNode(std::shared_ptr<Node> node); |
| |
| std::shared_ptr<Node> bound_node() { return bound_node_.lock(); } |
| std::string_view name() { return name_; } |
| |
| private: |
| std::string name_; |
| std::vector<zx_bind_inst_t> bind_rules_; |
| // This is a weak pointer because the node can be freed if its parents are |
| // removed. |
| std::weak_ptr<Node> bound_node_; |
| }; |
| |
| // This class will assemble a single composite device. It looks for nodes to |
| // match its fragments, and will create one composite node when it has all |
| // of its fragments matched. |
| class CompositeDeviceAssembler { |
| public: |
| // Create a CompositeDeviceAssembler. `binder` is unowned and must outlive |
| // the assembler class. |
| static zx::status<std::unique_ptr<CompositeDeviceAssembler>> Create( |
| std::string name, fuchsia_device_manager::CompositeDeviceDescriptor descriptor, |
| DriverBinder* binder, async_dispatcher_t* dispatcher); |
| |
| // Check the node against each fragment of this composite device. Returns |
| // true if it matches a fragment that is currently unbound. |
| // If this node is the last node needed for the composite device, this function |
| // will also create the composite node. |
| bool BindNode(std::shared_ptr<Node> node); |
| |
| private: |
| // Check if we have all of our fragments bound. If we do, then create the |
| // composite node. If we don't have all fragments bound, this does nothing. |
| void TryToAssemble(); |
| |
| std::string name_; |
| |
| async_dispatcher_t* dispatcher_; |
| DriverBinder* binder_; |
| |
| fidl::Arena<128> arena_; |
| // The properties of the composite device being created. This is backed |
| // by `arena_`. |
| std::vector<fuchsia_driver_framework::wire::NodeProperty> properties_; |
| |
| std::vector<CompositeDeviceFragment> fragments_; |
| }; |
| |
| // This class manages all of the `CompositeDeviceAssemblers` that exist. |
| class CompositeDeviceManager { |
| public: |
| // Create a CompositeDeviceManager. `binder` is unowned and must outlive the |
| // manager class. |
| CompositeDeviceManager(DriverBinder* binder, async_dispatcher_t* dispatcher); |
| |
| zx_status_t AddCompositeDevice(std::string name, |
| fuchsia_device_manager::CompositeDeviceDescriptor descriptor); |
| |
| // Check this node against all of the composite devices that need to be created. |
| // Returns true if the node was successfully bound. If the node was bound to |
| // a composite device, then there is no need to bind it to a driver. |
| bool BindNode(std::shared_ptr<Node> node); |
| |
| private: |
| DriverBinder* binder_; |
| async_dispatcher_t* dispatcher_; |
| std::vector<std::unique_ptr<CompositeDeviceAssembler>> assemblers_; |
| }; |
| |
| } // namespace dfv2 |
| |
| #endif // SRC_DEVICES_BIN_DRIVER_MANAGER_V2_COMPOSITE_ASSEMBLER_H_ |