blob: 49a9ef2bda1b3bb71ae070f4b5aa94f95b28123e [file] [log] [blame]
// 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_