blob: c4cd059eb8396652883b84bafa789204e5433d54 [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/driver2/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(), "default");
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();
}
// Serve the fuchsia.examples.acpi.multiply/Device protocol to clients through the
// fuchsia.examples.acpi.multiply/Service wrapper.
driver::ServiceInstanceHandler handler;
fuchsia_examples_acpi_multiply::Service::Handler service(&handler);
auto result = service.add_device(
[this](fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> request) -> void {
AcpiMultiplyServer::BindDeviceClient(&logger(), dispatcher(), multiplier_,
std::move(request));
});
ZX_ASSERT(result.is_ok());
result =
context().outgoing()->AddService<fuchsia_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();
}
// This is not strictly necessary, but it does a multiplication to prove that the driver
// behaves as expected.
async::PostTask(dispatcher(), [this]() {
auto endpoints = fidl::CreateEndpoints<fuchsia_examples_acpi_multiply::Device>();
if (endpoints.is_error()) {
FDF_LOG(ERROR, "Failed to create endpoints");
return;
}
auto server_impl = std::make_unique<AcpiMultiplyServer>(&logger(), multiplier_);
fidl::BindServer(dispatcher(), std::move(endpoints->server), std::move(server_impl),
std::mem_fn(&AcpiMultiplyServer::OnUnbound));
client_.Bind(std::move(endpoints->client), dispatcher());
// Do the multiply
client_->Multiply(UINT32_MAX, 9)
.Then([this](fidl::WireUnownedResult<fuchsia_examples_acpi_multiply::Device::Multiply>&
response) {
if (response.ok() && response->is_ok()) {
FDF_SLOG(INFO, "UINT32_MAX*9: Got result",
KV("result", response.value().value()->result),
KV("overflowed", response.value().value()->overflowed));
} else {
FDF_SLOG(ERROR, "Multiply failed",
KV("fidl status", (const char*)response.FormatDescription().data()),
KV("device status",
(const char*)(response.ok() ? response.status_string() : "N/A")));
}
});
client_->Multiply(2, 9).Then(
[this](
fidl::WireUnownedResult<fuchsia_examples_acpi_multiply::Device::Multiply>& response) {
if (response.ok() && response->is_ok()) {
FDF_SLOG(INFO, "2*9: Got result", KV("result", response.value().value()->result),
KV("overflowed", response.value().value()->overflowed));
} else {
FDF_SLOG(ERROR, "Multiply failed",
KV("fidl status", (const char*)response.FormatDescription().data()),
KV("device status",
(const char*)(response.ok() ? response.status_string() : "N/A")));
}
});
});
return zx::ok();
}
} // namespace acpi_multiply
FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<acpi_multiply::AcpiMultiplyDriver>);