blob: f5bfc06a3966a12da2b011e5b0a4b7a001e8748e [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 "parent-driver.h"
// [START bind_imports]
#include <bind/fuchsia/device/fs/cpp/bind.h>
#include <bind/fuchsia/examples/gizmo/bind/cpp/bind.h>
#include <bind/fuchsia/examples/gizmo/cpp/bind.h>
// [END bind_imports]
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace parent_driver {
// static
zx::status<std::unique_ptr<ParentDriver>> ParentDriver::Start(
fdf::wire::DriverStartArgs& start_args, fdf::UnownedDispatcher dispatcher,
fidl::WireSharedClient<fdf::Node> node, driver::Namespace ns, driver::Logger logger) {
auto driver = std::make_unique<ParentDriver>(dispatcher->async_dispatcher(), std::move(node),
std::move(ns), std::move(logger));
auto result = driver->Run(std::move(start_args.outgoing_dir()));
if (result.is_error()) {
return result.take_error();
}
return zx::ok(std::move(driver));
}
// private
zx::status<> ParentDriver::Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir) {
component::ServiceHandler handler;
fuchsia_examples_gizmo::Service::Handler service(&handler);
auto protocol_handler =
[this](fidl::ServerEnd<fuchsia_examples_gizmo::TestingProtocol> server_end) -> void {
fidl::BindServer<fidl::WireServer<fuchsia_examples_gizmo::TestingProtocol>>(
dispatcher_, std::move(server_end), this);
};
auto result = service.add_testing(protocol_handler);
ZX_ASSERT(result.is_ok());
result = outgoing_.AddService<fuchsia_examples_gizmo::Service>(std::move(handler));
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add service", KV("status", result.status_string()));
return result.take_error();
}
result = AddChild();
if (result.status_value() != ZX_OK) {
return result;
}
return outgoing_.Serve(std::move(outgoing_dir));
}
zx::status<> ParentDriver::AddChild() {
fidl::Arena arena;
// Offer `fuchsia.examples.gizmo.Service` to the driver that binds to the node.
auto service_offer = fuchsia_component_decl::wire::OfferService::Builder(arena)
.source_name(arena, fuchsia_examples_gizmo::Service::Name)
.target_name(arena, fuchsia_examples_gizmo::Service::Name)
.Build();
fuchsia_component_decl::wire::Offer offer =
fuchsia_component_decl::wire::Offer::WithService(arena, service_offer);
// Set the properties of the node that the child will bind to based on the child-driver.bind
// [START add_properties]
uint32_t key_a = 1 /* BIND_PROTOCOL */;
uint32_t val_a = bind_fuchsia_acpi::BIND_PROTOCOL_DEVICE;
std::string key_b = bind_fuchsia_acpi::HID;
std::string val_b = "GOOG";
std::string key_c = bind_fuchsia_device_fs::EXPORTER;
std::string val_c = bind_fuchsia_device_fs::EXPORTER_ZIRCONTRANSPORT;
std::string key_d = bind_fuchsia_examples_gizmo_bind::NAME;
std::string val_d = "GIZMO";
std::string key_e = bind_fuchsia_examples_gizmo::TESTINGPROTOCOL;
std::string val_e = bind_fuchsia_examples_gizmo::TESTINGPROTOCOL_ZIRCONTRANSPORT;
// [END add_properties]
auto properties = fidl::VectorView<fdf::wire::NodeProperty>(arena, 5);
properties[0] = fdf::wire::NodeProperty::Builder(arena)
.key(fdf::wire::NodePropertyKey::WithIntValue(key_a))
.value(fdf::wire::NodePropertyValue::WithIntValue(val_a))
.Build();
properties[1] = fdf::wire::NodeProperty::Builder(arena)
.key(fdf::wire::NodePropertyKey::WithStringValue(arena, key_b))
.value(fdf::wire::NodePropertyValue::WithStringValue(arena, val_b))
.Build();
// We are not actually offering the Exporter protocol to the child, nor using it from the child.
// This is just to demonstrate access to these values through the auto-generated bind library.
properties[2] = fdf::wire::NodeProperty::Builder(arena)
.key(fdf::wire::NodePropertyKey::WithStringValue(arena, key_c))
.value(fdf::wire::NodePropertyValue::WithEnumValue(arena, val_c))
.Build();
properties[3] = fdf::wire::NodeProperty::Builder(arena)
.key(fdf::wire::NodePropertyKey::WithStringValue(arena, key_d))
.value(fdf::wire::NodePropertyValue::WithStringValue(arena, val_d))
.Build();
properties[4] = fdf::wire::NodeProperty::Builder(arena)
.key(fdf::wire::NodePropertyKey::WithStringValue(arena, key_e))
.value(fdf::wire::NodePropertyValue::WithEnumValue(arena, val_e))
.Build();
auto args =
fdf::wire::NodeAddArgs::Builder(arena)
.name(arena, "bindlib-child")
.offers(fidl::VectorView<fuchsia_component_decl::wire::Offer>::FromExternal(&offer, 1))
.properties(properties)
.Build();
// Create endpoints of the `NodeController` for the node.
auto endpoints = fidl::CreateEndpoints<fdf::NodeController>();
if (endpoints.is_error()) {
FDF_SLOG(ERROR, "Failed to create endpoint", KV("status", endpoints.status_string()));
return zx::error(endpoints.status_value());
}
auto result = node_.sync()->AddChild(args, std::move(endpoints->server), {});
if (!result.ok()) {
FDF_SLOG(ERROR, "Failed to add child", KV("status", result.status_string()));
return zx::error(result.status());
}
return zx::ok();
}
void ParentDriver::Get(GetRequestView request, GetCompleter::Sync& completer) {
FDF_LOG(INFO, "Received TestingProtocol.Get request.");
}
} // namespace parent_driver
FUCHSIA_DRIVER_RECORD_CPP_V1(parent_driver::ParentDriver);