| // 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 = |
| driver::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. |
| component::ServiceInstanceHandler handler; |
| examples_acpi_multiply::Service::Handler service(&handler); |
| |
| auto result = |
| service.add_device([this](fidl::ServerEnd<examples_acpi_multiply::Device> request) -> void { |
| AcpiMultiplyServer::BindDeviceClient(&logger(), dispatcher(), multiplier_, |
| std::move(request)); |
| }); |
| ZX_ASSERT(result.is_ok()); |
| |
| 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 `examples.acpi.multiply/Service` 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); |
| |
| auto service_path = std::string(examples_acpi_multiply::Service::Name) + "/" + |
| component::kDefaultInstance + "/" + |
| examples_acpi_multiply::Service::Device::Name; |
| auto status = compat_context_->devfs_exporter().ExportSync( |
| service_path, compat_context_->TopologicalPath(name()), fuchsia_device_fs::ExportOptions()); |
| if (status != ZX_OK) { |
| FDF_SLOG(ERROR, "Failed to export to devfs.", KV("status", zx_status_get_string(status))); |
| node().reset(); |
| return; |
| } |
| } |
| |
| } // namespace acpi_multiply |
| |
| FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<acpi_multiply::AcpiMultiplyDriver>); |