| // 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); |