blob: 2fafc59b4af4df6aa016d6165d3a6837d3842f82 [file] [log] [blame]
// 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 "src/devices/tests/runtime-composite-test/drivers/root-driver.h"
#include <lib/ddk/binding_driver.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <bind/composite/test/lib/cpp/bind.h>
#include <bind/fuchsia/cpp/bind.h>
#include <bind/fuchsia/test/cpp/bind.h>
namespace bind_test = bind_composite_test_lib;
namespace frct = fuchsia_runtime_composite_test;
namespace root_driver {
zx_status_t RootDriver::Bind(void* ctx, zx_device_t* dev) {
auto root_dev = std::make_unique<RootDriver>(dev);
zx_status_t status = root_dev->DdkAdd(ddk::DeviceAddArgs("root"));
if (status != ZX_OK) {
return status;
}
[[maybe_unused]] auto ptr = root_dev.release();
// Add 2 children that matches the first composite node spec node.
zx_device_str_prop_t str_fragment_props[] = {
{bind_test::FLAG, str_prop_bool_val(true)},
};
auto dispatcher = fdf::Dispatcher::GetCurrent();
auto fragment_dev_a = std::make_unique<RootDriver>(dev, dispatcher->get());
auto client_end = fragment_dev_a->RegisterRuntimeService();
if (client_end.is_error()) {
return client_end.status_value();
}
std::array offers = {
frct::Service::Name,
};
status = fragment_dev_a->DdkAdd(ddk::DeviceAddArgs("composite_fragment_a")
.set_str_props(str_fragment_props)
.set_proto_id(bind_fuchsia_test::BIND_PROTOCOL_COMPAT_CHILD)
.set_runtime_service_offers(offers)
.set_outgoing_dir(client_end->TakeChannel()));
if (status != ZX_OK) {
return status;
}
[[maybe_unused]] auto fragment_a_ptr = fragment_dev_a.release();
// Add the leaf device.
zx_device_str_prop_t leaf_props[] = {
ddk::MakeStrProperty(bind_fuchsia::PROTOCOL, bind_fuchsia_test::BIND_PROTOCOL_DEVICE),
};
auto leaf_dev = std::make_unique<RootDriver>(dev);
status = leaf_dev->DdkAdd(ddk::DeviceAddArgs("leaf")
.set_str_props(leaf_props)
.set_proto_id(bind_fuchsia_test::BIND_PROTOCOL_DEVICE));
if (status != ZX_OK) {
return status;
}
[[maybe_unused]] auto leaf_ptr = leaf_dev.release();
// Add 2 devices that matches the other composite node spec node.
zx_device_str_prop_t str_fragment_props_2[] = {
{bind_test::TEST_PROP, str_prop_str_val(bind_test::TEST_PROP_VALUE_2)},
};
auto fragment_dev_b = std::make_unique<RootDriver>(dev);
status = fragment_dev_b->DdkAdd(ddk::DeviceAddArgs("composite_fragment_b")
.set_str_props(str_fragment_props_2)
.set_proto_id(bind_fuchsia_test::BIND_PROTOCOL_COMPAT_CHILD));
if (status != ZX_OK) {
return status;
}
[[maybe_unused]] auto fragment_b_ptr = fragment_dev_b.release();
return ZX_OK;
}
void RootDriver::DdkRelease() { delete this; }
void RootDriver::Handshake(HandshakeCompleter::Sync& completer) { completer.Reply(fit::ok()); }
zx::result<fidl::ClientEnd<fuchsia_io::Directory>> RootDriver::RegisterRuntimeService() {
auto protocol = [this](fdf::ServerEnd<frct::RuntimeCompositeProtocol> server_end) mutable {
fdf::BindServer(fdf::Dispatcher::GetCurrent()->get(), std::move(server_end), this);
};
frct::Service::InstanceHandler handler({.runtime_composite_protocol = std::move(protocol)});
auto add_status = outgoing_->AddService<frct::Service>(std::move(handler));
if (add_status.is_error()) {
return add_status.take_error();
}
auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
if (endpoints.is_error()) {
return endpoints.take_error();
}
auto result = outgoing_->Serve(std::move(endpoints->server));
if (result.is_error()) {
return result.take_error();
}
return zx::ok(std::move(endpoints->client));
}
static zx_driver_ops_t root_driver_driver_ops = []() -> zx_driver_ops_t {
zx_driver_ops_t ops = {};
ops.version = DRIVER_OPS_VERSION;
ops.bind = RootDriver::Bind;
return ops;
}();
} // namespace root_driver
ZIRCON_DRIVER(RootDriver, root_driver::root_driver_driver_ops, "zircon", "0.1");