blob: 17d893a40cf49bb33bffd80e30b5efe37b5a68a7 [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.
#include <fidl/fuchsia.power.broker/cpp/fidl.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/component/cpp/internal/start_args.h>
#include <lib/driver/logging/cpp/logger.h>
#include <lib/inspect/component/cpp/component.h>
#include <zircon/availability.h>
namespace fdf {
#if FUCHSIA_API_LEVEL_LESS_THAN(29)
__WEAK bool logger_wait_for_initial_interest = true;
#endif
DriverBase::DriverBase(std::string_view name, DriverStartArgs start_args,
fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: name_(name),
start_args_(std::move(start_args)),
driver_dispatcher_(std::move(driver_dispatcher)) {
Namespace incoming = [ns = std::move(start_args_.incoming())]() mutable {
ZX_ASSERT(ns.has_value());
zx::result incoming = Namespace::Create(ns.value());
ZX_ASSERT_MSG(incoming.is_ok(), "%s", incoming.status_string());
return std::move(incoming.value());
}();
logger_ = [&incoming, this]() {
auto logger = Logger::Create2(incoming, dispatcher(), name_, FUCHSIA_LOG_INFO
#if FUCHSIA_API_LEVEL_LESS_THAN(29)
,
logger_wait_for_initial_interest
#endif
);
return logger;
}();
Logger::SetGlobalInstance(logger_.get());
std::optional outgoing_request = std::move(start_args_.outgoing_dir());
ZX_ASSERT(outgoing_request.has_value());
InitializeAndServe(std::move(incoming), std::move(outgoing_request.value()));
zx::result val = fdf_internal::ProgramValue(program(), "service_connect_validation");
if (val.is_ok() && val.value() == "true") {
EnableServiceValidator();
}
}
void DriverBase::RegisterInitMethods(InitMethodCallback cb) {
init_methods_.push_back(std::move(cb));
}
zx::result<> DriverBase::RunInitMethods() {
for (auto& method : init_methods_) {
zx::result result = method(dispatcher(), *incoming(), name());
if (result.is_error()) {
return result.take_error();
}
}
return zx::ok();
}
#if FUCHSIA_API_LEVEL_AT_LEAST(HEAD)
std::optional<fidl::ServerEnd<fuchsia_power_broker::ElementRunner>>
DriverBase::take_power_element_runner() {
if (!start_args_.power_element_args().has_value()) {
return std::nullopt;
}
return fidl::ServerEnd<fuchsia_power_broker::ElementRunner>(
start_args_.power_element_args()->runner_server()->TakeChannel());
}
std::optional<fidl::ClientEnd<fuchsia_power_broker::Lessor>>
DriverBase::take_power_element_lessor() {
if (!start_args_.power_element_args().has_value()) {
return std::nullopt;
}
return fidl::ClientEnd<fuchsia_power_broker::Lessor>(
std::move(start_args_.power_element_args()->lessor_client().value()));
}
std::optional<fuchsia_power_broker::DependencyToken> DriverBase::power_element_token() {
if (!start_args_.power_element_args().has_value()) {
return std::nullopt;
}
zx::event copy;
ZX_ASSERT(start_args_.power_element_args()->token()->duplicate(ZX_RIGHT_SAME_RIGHTS, &copy) !=
ZX_OK);
return fuchsia_power_broker::DependencyToken(std::move(copy));
}
#endif
void DriverBase::InitializeAndServe(
Namespace incoming, fidl::ServerEnd<fuchsia_io::Directory> outgoing_directory_request) {
incoming_ = std::make_shared<Namespace>(std::move(incoming));
outgoing_ =
std::make_shared<OutgoingDirectory>(OutgoingDirectory::Create(driver_dispatcher_->get()));
ZX_ASSERT(outgoing_->Serve(std::move(outgoing_directory_request)).is_ok());
}
void DriverBase::EnableServiceValidator() {
if (start_args_.node_offers().has_value()) {
incoming_->SetServiceValidator(
std::make_optional<ServiceValidator>(start_args_.node_offers().value()));
} else {
FDF_LOGL(INFO, *logger_, "No node_offers available, not able to enable service validation.");
}
}
void DriverBase::InitInspectorExactlyOnce(inspect::Inspector inspector) {
std::call_once(init_inspector_once_, [&] {
inspector_.emplace(
dispatcher(), inspect::PublishOptions{
.inspector = std::move(inspector),
.tree_name = {name_},
.client_end = incoming()->Connect<fuchsia_inspect::InspectSink>().value(),
});
});
}
#if FUCHSIA_API_LEVEL_AT_MOST(26)
cpp20::span<const fuchsia_driver_framework::NodeProperty> DriverBase::node_properties(
const std::string& parent_node_name) const {
const auto& node_properties = start_args_.node_properties();
if (node_properties.has_value()) {
for (const auto& entry : node_properties.value()) {
if (entry.name() == parent_node_name) {
return entry.properties();
}
}
}
return {};
}
#endif
zx::result<OwnedChildNode> DriverBase::AddOwnedChild(std::string_view node_name) {
return fdf::AddOwnedChild(node(), logger(), node_name);
}
zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> DriverBase::AddChild(
std::string_view node_name,
cpp20::span<const fuchsia_driver_framework::NodeProperty> properties,
cpp20::span<const fuchsia_driver_framework::Offer> offers) {
return fdf::AddChild(node(), logger(), node_name, properties, offers);
}
zx::result<OwnedChildNode> DriverBase::AddOwnedChild(
std::string_view node_name, fuchsia_driver_framework::DevfsAddArgs& devfs_args) {
return fdf::AddOwnedChild(node(), logger(), node_name, devfs_args);
}
zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> DriverBase::AddChild(
std::string_view node_name, fuchsia_driver_framework::DevfsAddArgs& devfs_args,
cpp20::span<const fuchsia_driver_framework::NodeProperty> properties,
cpp20::span<const fuchsia_driver_framework::Offer> offers) {
return fdf::AddChild(node(), logger(), node_name, devfs_args, properties, offers);
}
zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> DriverBase::AddChild(
std::string_view node_name,
cpp20::span<const fuchsia_driver_framework::NodeProperty2> properties,
cpp20::span<const fuchsia_driver_framework::Offer> offers) {
return fdf::AddChild(node(), logger(), node_name, properties, offers);
}
zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> DriverBase::AddChild(
std::string_view node_name, fuchsia_driver_framework::DevfsAddArgs& devfs_args,
cpp20::span<const fuchsia_driver_framework::NodeProperty2> properties,
cpp20::span<const fuchsia_driver_framework::Offer> offers) {
return fdf::AddChild(node(), logger(), node_name, devfs_args, properties, offers);
}
cpp20::span<const fuchsia_driver_framework::NodeProperty2> DriverBase::node_properties_2(
const std::string& parent_node_name) const {
const auto& node_properties_2 = start_args_.node_properties_2();
if (node_properties_2.has_value()) {
for (const auto& entry : node_properties_2.value()) {
if (entry.name() == parent_node_name) {
return entry.properties();
}
}
}
return {};
}
DriverBase::~DriverBase() { Logger::SetGlobalInstance(nullptr); }
} // namespace fdf