| // 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 "acpi_multiply.h" |
| |
| #include <fidl/fuchsia.hardware.acpi/cpp/wire.h> |
| #include <lib/async/cpp/task.h> |
| #include <lib/driver/component/cpp/service_client.h> |
| |
| #include "multiply_server.h" |
| |
| namespace acpi_multiply { |
| |
| zx::result<> AcpiMultiplyDriver::Start() { |
| // Connect to the ACPI protocol exposed by the parent driver. |
| auto client_endpoint = |
| fdf::Connect<fuchsia_hardware_acpi::Service::Device>(*context().incoming()); |
| if (client_endpoint.is_error()) { |
| FDF_SLOG(ERROR, "Failed to connect to ACPI.", KV("status", client_endpoint.status_string())); |
| return client_endpoint.take_error(); |
| } |
| auto acpi_client = fidl::WireSyncClient(std::move(*client_endpoint)); |
| |
| // Initialize ACPI hardware resources |
| multiplier_ = std::make_shared<AcpiMultiplier>(&logger(), dispatcher(), std::move(acpi_client)); |
| auto init_result = multiplier_->SetupMmioAndInterrupts(); |
| if (init_result.is_error()) { |
| FDF_SLOG(ERROR, "Failed to initialize ACPI resources.", |
| KV("status", init_result.status_string())); |
| return init_result.take_error(); |
| } |
| FDF_LOG(INFO, "Hardware resources initialized."); |
| |
| // Serve the examples.acpi.multiply/Device protocol to clients through the |
| // examples.acpi.multiply/Service wrapper. |
| examples_acpi_multiply::Service::InstanceHandler handler({ |
| .device = fit::bind_member<&AcpiMultiplyDriver::Serve>(this), |
| }); |
| |
| auto result = |
| context().outgoing()->AddService<examples_acpi_multiply::Service>(std::move(handler)); |
| if (result.is_error()) { |
| FDF_SLOG(ERROR, "Failed to add service.", KV("status", result.status_string())); |
| return result.take_error(); |
| } |
| |
| // Initialize the driver compat service context. |
| compat::Context::ConnectAndCreate( |
| &context(), dispatcher(), |
| fit::bind_member<&AcpiMultiplyDriver::InitializeCompatService>(this)); |
| |
| return zx::ok(); |
| } |
| |
| // Initialize the driver compat context and export `fuchsia_acpi_multiply::Device` to |
| // devfs. |
| void AcpiMultiplyDriver::InitializeCompatService( |
| zx::result<std::shared_ptr<compat::Context>> compat_result) { |
| if (!compat_result.is_ok()) { |
| FDF_SLOG(ERROR, "Failed to create compat context.", |
| KV("status", compat_result.status_string())); |
| node().reset(); |
| return; |
| } |
| compat_context_ = std::move(*compat_result); |
| |
| // Export to devfs. |
| zx::result connection = this->context().incoming()->Connect<fuchsia_device_fs::Exporter>(); |
| if (connection.is_error()) { |
| FDF_SLOG(ERROR, "Failed to connect to fuchsia_device_fs::Exporter", |
| KV("status", connection.status_string())); |
| node().reset(); |
| return; |
| } |
| fidl::WireSyncClient devfs_exporter{std::move(connection.value())}; |
| |
| zx::result connector = devfs_connector_.Bind(dispatcher()); |
| if (connector.is_error()) { |
| FDF_SLOG(ERROR, "Failed to bind devfs_connector: %s", KV("status", connector.status_string())); |
| node().reset(); |
| return; |
| } |
| fidl::WireResult export_result = devfs_exporter->ExportV2( |
| std::move(connector.value()), |
| fidl::StringView::FromExternal(compat_context_->TopologicalPath(name())), |
| fidl::StringView(), fuchsia_device_fs::ExportOptions()); |
| if (!export_result.ok()) { |
| FDF_SLOG(ERROR, "Failed to export to devfs: %s", KV("status", export_result.status_string())); |
| node().reset(); |
| return; |
| } |
| if (export_result.value().is_error()) { |
| FDF_SLOG(ERROR, "Failed to export to devfs: %s", |
| KV("status", zx_status_get_string(export_result.value().error_value()))); |
| node().reset(); |
| return; |
| } |
| } |
| |
| void AcpiMultiplyDriver::Serve(fidl::ServerEnd<examples_acpi_multiply::Device> request) { |
| AcpiMultiplyServer::BindDeviceClient(&logger(), dispatcher(), multiplier_, std::move(request)); |
| } |
| |
| } // namespace acpi_multiply |
| |
| FUCHSIA_DRIVER_RECORD_CPP_V2(fdf::Record<acpi_multiply::AcpiMultiplyDriver>); |