blob: 453f035dee49ea9e852a9eb64e35f8c3740138b9 [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.
#include "src/devices/bin/driver_manager/composite_node_spec/composite_node_spec.h"
namespace driver_manager {
CompositeNodeSpec::CompositeNodeSpec(CompositeNodeSpecCreateInfo create_info)
: name_(create_info.name) {
parent_nodes_ =
std::vector<std::optional<DeviceOrNode>>(create_info.parents.size(), std::nullopt);
parent_specs_ = std::move(create_info.parents);
}
zx::result<std::optional<DeviceOrNode>> CompositeNodeSpec::BindParent(
fuchsia_driver_framework::wire::CompositeParent composite_parent,
const DeviceOrNode& device_or_node) {
ZX_ASSERT(composite_parent.has_index());
auto node_index = composite_parent.index();
if (node_index >= parent_nodes_.size()) {
return zx::error(ZX_ERR_OUT_OF_RANGE);
}
const std::optional<DeviceOrNode>& current_at_index = parent_nodes_[node_index];
if (current_at_index.has_value()) {
const DeviceOrNode& existing = current_at_index.value();
const std::weak_ptr<driver_manager::Node>* existing_node =
std::get_if<std::weak_ptr<driver_manager::Node>>(&existing);
// If the driver_manager::Node no longer exists (for example because of a reload) then we don't
// want to return an ALREADY_BOUND error.
if (!existing_node || !existing_node->expired()) {
return zx::error(ZX_ERR_ALREADY_BOUND);
}
}
auto result = BindParentImpl(composite_parent, device_or_node);
if (result.is_ok()) {
parent_nodes_[node_index] = device_or_node;
}
return result;
}
void CompositeNodeSpec::Remove(RemoveCompositeNodeCallback callback) {
std::fill(parent_nodes_.begin(), parent_nodes_.end(), std::nullopt);
RemoveImpl(std::move(callback));
}
} // namespace driver_manager