blob: e04b9193d03af160e9c6dd1f2b09c2690cb54dba [file] [log] [blame]
// Copyright 2021 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 <lib/ddk/device.h>
#include <lib/driver/compat/cpp/compat.h>
#include <lib/driver/compat/cpp/symbols.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/component/cpp/driver_export.h>
#include <lib/driver/component/cpp/node_add_args.h>
#include <bind/fuchsia/test/cpp/bind.h>
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace {
class RootDriver : public fdf::DriverBase {
public:
RootDriver(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: fdf::DriverBase("root", std::move(start_args), std::move(driver_dispatcher)) {}
void Start(fdf::StartCompleter completer) override {
node_.Bind(std::move(node()), dispatcher());
start_completer_.emplace(std::move(completer));
child_.Begin(incoming(), outgoing(), node_name(), "v1",
fit::bind_member<&RootDriver::CompatServerInitialized>(this),
compat::ForwardMetadata::None(), get_banjo_config());
}
void CompleteStart(zx::result<> result) {
ZX_ASSERT(start_completer_.has_value());
start_completer_.value()(result);
start_completer_.reset();
}
void CompatServerInitialized(zx::result<> compat_result) {
if (compat_result.is_error()) {
return CompleteStart(compat_result.take_error());
}
// Set the properties of the node that a driver will bind to.
fdf::NodeProperty property =
fdf::MakeProperty(1 /* BIND_PROTOCOL */, bind_fuchsia_test::BIND_PROTOCOL_COMPAT_CHILD);
auto offers = child_.CreateOffers2();
fdf::NodeAddArgs args({.name = "v1", .properties = {{property}}, .offers2 = offers});
// Create endpoints of the `NodeController` for the node.
auto endpoints = fidl::CreateEndpoints<fdf::NodeController>();
if (endpoints.is_error()) {
return CompleteStart(endpoints.take_error());
}
node_->AddChild({std::move(args), std::move(endpoints->server), {}})
.Then([this, client = std::move(endpoints->client)](
fidl::Result<fdf::Node::AddChild>& add_result) mutable {
if (add_result.is_error()) {
FDF_LOG(ERROR, "Failed to AddChild: %s",
add_result.error_value().FormatDescription().c_str());
node_.AsyncTeardown();
return;
}
controller_.Bind(std::move(client), dispatcher());
CompleteStart(zx::ok());
});
}
private:
compat::DeviceServer::BanjoConfig get_banjo_config() {
compat::DeviceServer::BanjoConfig config{0};
config.callbacks[0] = []() {
return compat::DeviceServer::GenericProtocol{.ops = nullptr, .ctx = nullptr};
};
return config;
}
fidl::SharedClient<fdf::Node> node_;
fidl::SharedClient<fdf::NodeController> controller_;
std::optional<fdf::StartCompleter> start_completer_;
compat::AsyncInitializedDeviceServer child_;
};
} // namespace
FUCHSIA_DRIVER_EXPORT(RootDriver);