blob: 4bfe4b93afd98fabd446fc621857f96e2d97ed62 [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 "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>);