[acpi] Update the drivers to the DriverBase lib
Updates the acpi_multiply sample drivers to the new DriverBase library.
Also makes the following semi-related changes:
- Remove unnecessary includes and build deps
- Use bind library code gen library
- Start using services for hardware.acpi
- Split out hardware.acpi fidl server from driver
Bug: 110283, 110915, 106665
Tests: Ran through the README.md instructions successfully
Change-Id: Iafd44a4b777fbd6f0c19650ec8b102db776ddee7
Reviewed-on: https://fuchsia-review.googlesource.com/c/sdk-samples/drivers/+/733645
Reviewed-by: David Gilhooley <dgilhooley@google.com>
Commit-Queue: Novin Changizi <novinc@google.com>
Reviewed-by: Dave Smith <smithdave@google.com>
Reviewed-by: Suraj Malhotra <surajmalhotra@google.com>
diff --git a/src/acpi_multiply/controller/BUILD.bazel b/src/acpi_multiply/controller/BUILD.bazel
index f50ba34..e2020a2 100644
--- a/src/acpi_multiply/controller/BUILD.bazel
+++ b/src/acpi_multiply/controller/BUILD.bazel
@@ -4,7 +4,6 @@
load(
"@rules_fuchsia//fuchsia:defs.bzl",
- "fuchsia_cc_binary",
"fuchsia_component_manifest",
"fuchsia_driver_bind_bytecode",
"fuchsia_driver_component",
@@ -25,22 +24,18 @@
srcs = [
"acpi_controller.cc",
"acpi_controller.h",
+ "acpi_server.cc",
+ "acpi_server.h",
],
linkshared = True,
deps = [
"//src/acpi_multiply/lib",
- "@fuchsia_sdk//fidl/fuchsia.device.fs:fuchsia.device.fs_llcpp_cc",
- "@fuchsia_sdk//fidl/fuchsia.driver.compat:fuchsia.driver.compat_llcpp_cc",
+ "@fuchsia_sdk//bind/fuchsia.acpi:fuchsia.acpi_cc",
"@fuchsia_sdk//fidl/fuchsia.hardware.acpi:fuchsia.hardware.acpi_bindlib_cc",
"@fuchsia_sdk//fidl/fuchsia.hardware.acpi:fuchsia.hardware.acpi_llcpp_cc",
- "@fuchsia_sdk//fidl/zx:zx_cc",
"@fuchsia_sdk//pkg/async-cpp",
"@fuchsia_sdk//pkg/driver2_cpp",
- "@fuchsia_sdk//pkg/hwreg",
"@fuchsia_sdk//pkg/mmio",
- "@fuchsia_sdk//pkg/fidl_cpp_wire",
- "@fuchsia_sdk//pkg/sys_component_cpp",
- "@fuchsia_sdk//pkg/zx",
],
)
@@ -52,7 +47,6 @@
],
)
-
fuchsia_driver_component(
name = "component",
bind_bytecode = ":bind_bytecode",
diff --git a/src/acpi_multiply/controller/acpi_controller.cc b/src/acpi_multiply/controller/acpi_controller.cc
index 9145a32..4b9e9aa 100644
--- a/src/acpi_multiply/controller/acpi_controller.cc
+++ b/src/acpi_multiply/controller/acpi_controller.cc
@@ -4,215 +4,118 @@
#include "acpi_controller.h"
-#include <fidl/fuchsia.component.decl/cpp/wire_types.h>
-#include <fidl/fuchsia.driver.framework/cpp/wire.h>
-#include <fidl/fuchsia.hardware.acpi/cpp/wire_types.h>
-#include <fidl/fuchsia.mem/cpp/wire_types.h>
-#include <lib/async/cpp/task.h>
-#include <lib/driver2/record_cpp.h>
-#include <lib/driver2/structured_logger.h>
-#include <lib/fidl/cpp/wire/connect_service.h>
-#include <lib/zx/clock.h>
-#include <zircon/errors.h>
-#include <zircon/syscalls.h>
-#include <zircon/types.h>
-
+#include <bind/fuchsia/acpi/cpp/bind.h>
#include <bind/fuchsia/hardware/acpi/cpp/bind.h>
-#include "registers.h"
-
namespace acpi_multiply {
-zx::status<std::unique_ptr<AcpiMultiplyController>> AcpiMultiplyController::Start(
- fuchsia_driver_framework::wire::DriverStartArgs &start_args, fdf::UnownedDispatcher dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
- driver::Logger logger) {
- auto driver = std::make_unique<AcpiMultiplyController>(
- dispatcher->async_dispatcher(), std::move(node), std::move(ns), std::move(logger));
+zx::status<> AcpiMultiplyController::Start() {
+ node_.Bind(std::move(node()));
- auto result = driver->Run(std::move(start_args.outgoing_dir()));
+ auto server_result = InitializeServer();
+ if (server_result.is_error()) {
+ FDF_LOG(ERROR, "Failed to initialize ACPI Server: %s",
+ zx_status_get_string(server_result.error_value()));
+ return server_result.take_error();
+ }
+
+ // Serve the fuchsia.hardware.acpi/Device protocol to clients through the
+ // fuchsia.hardware.acpi/Service wrapper.
+ driver::ServiceInstanceHandler handler;
+ fuchsia_hardware_acpi::Service::Handler service(&handler);
+ auto result =
+ service.add_device([this](fidl::ServerEnd<fuchsia_hardware_acpi::Device> request) -> void {
+ AcpiDeviceServer::BindDeviceClient(server_, async_dispatcher(), std::move(request));
+ });
if (result.is_error()) {
return result.take_error();
}
- return zx::ok(std::move(driver));
+ result = context().outgoing()->AddService<fuchsia_hardware_acpi::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.is_error()) {
+ return result.take_error();
+ }
+
+ return zx::ok();
}
-zx::status<> AcpiMultiplyController::Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir) {
+zx::status<> AcpiMultiplyController::InitializeServer() {
// Allocate an MMIO buffer representing the ACPI multiply device
zx::vmo vmo;
zx_status_t raw_status = zx::vmo::create(zx_system_get_page_size(), 0, &vmo);
if (raw_status != ZX_OK) {
+ FDF_LOG(ERROR, "Failed to create vmo: %s.", zx_status_get_string(raw_status));
return zx::error(raw_status);
}
auto buffer = fdf::MmioBuffer::Create(0, zx_system_get_page_size(), std::move(vmo),
ZX_CACHE_POLICY_UNCACHED_DEVICE);
if (buffer.is_error()) {
+ FDF_LOG(ERROR, "Failed to create mmio buffer: %s.", zx_status_get_string(buffer.error_value()));
return buffer.take_error();
}
- buffer_ = std::move(buffer.value());
// Create an IRQ resource for the ACPI multiply device
- raw_status = zx::interrupt::create(zx::resource(), 0, ZX_INTERRUPT_VIRTUAL, &irq_);
+ zx::interrupt irq;
+ raw_status = zx::interrupt::create(zx::resource(), 0, ZX_INTERRUPT_VIRTUAL, &irq);
if (raw_status != ZX_OK) {
+ FDF_LOG(ERROR, "Failed to create interrupt: %s.", zx_status_get_string(raw_status));
return zx::error(raw_status);
}
- // Serve `fuchsia.hardware.acpi/Device` to child device nodes
- auto service = [this](fidl::ServerEnd<fuchsia_hardware_acpi::Device> server_end) {
- fidl::BindServer(dispatcher_, std::move(server_end), this);
- };
-
- auto status = outgoing_.AddProtocol<fuchsia_hardware_acpi::Device>(std::move(service));
- if (status.is_error()) {
- FDF_SLOG(ERROR, "Failed to add protocol", KV("status", status.status_string()));
- return status;
- }
-
- status = AddChild();
- if (status.is_error()) {
- return status;
- }
-
- return outgoing_.Serve(std::move(outgoing_dir));
+ server_ = std::make_shared<AcpiDeviceServer>(std::move(irq), std::move(buffer.value()), logger_,
+ async_dispatcher());
+ return zx::ok();
}
zx::status<> AcpiMultiplyController::AddChild() {
fidl::Arena arena;
-
- // Offer fuchsia.hardware.acpi.Device to the driver that binds to the node.
- auto protocol_offer =
- fuchsia_component_decl::wire::OfferProtocol::Builder(arena)
- .source_name(arena, fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>)
- .target_name(arena, fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>)
- .dependency_type(fuchsia_component_decl::wire::DependencyType::kStrong)
- .Build();
- fuchsia_component_decl::wire::Offer offer =
- fuchsia_component_decl::wire::Offer::WithProtocol(arena, protocol_offer);
+ // Offer fuchsia.hardware.acpi.Service to the driver that binds to the node.
+ auto offers = fidl::VectorView<fuchsia_component_decl::wire::Offer>(arena, 1);
+ offers[0] = driver::MakeOffer<fuchsia_hardware_acpi::Service>(arena, "default");
// Set the properties of the node that a driver binds to.
auto properties = fidl::VectorView<fuchsia_driver_framework::wire::NodeProperty>(arena, 2);
- properties[0] = fuchsia_driver_framework::wire::NodeProperty::Builder(arena)
- .key(fuchsia_driver_framework::wire::NodePropertyKey::WithStringValue(
- arena, bind_fuchsia_hardware_acpi::DEVICE))
- .value(fuchsia_driver_framework::wire::NodePropertyValue::WithEnumValue(
- arena, bind_fuchsia_hardware_acpi::DEVICE_ZIRCONTRANSPORT))
- .Build();
+ properties[0] = driver::MakeEnumProperty(arena, bind_fuchsia_hardware_acpi::DEVICE,
+ bind_fuchsia_hardware_acpi::DEVICE_ZIRCONTRANSPORT);
+ properties[1] = driver::MakeProperty(arena, bind_fuchsia_acpi::HID, "FDFS0001");
- properties[1] = fuchsia_driver_framework::wire::NodeProperty::Builder(arena)
- .key(fuchsia_driver_framework::wire::NodePropertyKey::WithStringValue(
- arena, fidl::StringView::FromExternal("fuchsia.acpi.hid")))
- .value(fuchsia_driver_framework::wire::NodePropertyValue::WithStringValue(
- arena, fidl::StringView::FromExternal("FDFS0001")))
- .Build();
-
- auto args =
- fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
- .name(arena, "acpi-child")
- .offers(fidl::VectorView<fuchsia_component_decl::wire::Offer>::FromExternal(&offer, 1))
- .properties(properties)
- .Build();
+ auto args = fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
+ .name(arena, "acpi-child")
+ .offers(offers)
+ .properties(properties)
+ .Build();
// Create endpoints of the `NodeController` for the node.
auto endpoints = fidl::CreateEndpoints<fuchsia_driver_framework::NodeController>();
if (endpoints.is_error()) {
FDF_SLOG(ERROR, "Failed to create endpoint", KV("status", endpoints.status_string()));
- return zx::error(endpoints.status_value());
+ return endpoints.take_error();
}
- auto result = node_.sync()->AddChild(args, std::move(endpoints->server), {});
+ auto result = node_->AddChild(args, std::move(endpoints->server), {});
if (!result.ok()) {
- FDF_SLOG(ERROR, "Failed to add child", KV("status", result.status_string()));
+ FDF_SLOG(ERROR, "Failed to add child", KV("error_desc", result.FormatDescription().c_str()));
return zx::error(result.status());
}
+ if (result->is_error()) {
+ FDF_SLOG(ERROR, "Failed to add child",
+ KV("status", std::to_string(static_cast<uint32_t>(result->error_value())).c_str()));
+ return zx::error(ZX_ERR_INTERNAL);
+ }
+
+ controller_.Bind(std::move(endpoints->client));
+
return zx::ok();
}
-// Protocol method for `fuchsia.hardware.acpi/Device` to return a requested MMIO region.
-void AcpiMultiplyController::GetMmio(GetMmioRequestView request,
- GetMmioCompleter::Sync &completer) {
- if (request->index != 0) {
- completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
- return;
- }
-
- zx::vmo clone;
- zx_status_t status = buffer_->get_vmo()->duplicate(ZX_RIGHT_SAME_RIGHTS, &clone);
- if (status != ZX_OK) {
- completer.ReplyError(status);
- return;
- }
-
- completer.ReplySuccess(fuchsia_mem::wire::Range{
- .vmo = std::move(clone),
- .offset = 0,
- .size = zx_system_get_page_size(),
- });
-}
-
-// Protocol method for `fuchsia.hardware.acpi/Device` to return the requested IRQ.
-void AcpiMultiplyController::MapInterrupt(MapInterruptRequestView request,
- MapInterruptCompleter::Sync &completer) {
- if (request->index != 0) {
- completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
- return;
- }
-
- zx::interrupt clone;
- zx_status_t status = irq_.duplicate(ZX_RIGHT_SAME_RIGHTS, &clone);
- if (status != ZX_OK) {
- completer.ReplyError(status);
- return;
- }
-
- completer.ReplySuccess(std::move(clone));
-}
-
-// Protocol method for `fuchsia.hardware.acpi/Device` to interpret an invoke the control method
-// associated with the provided object path.
-void AcpiMultiplyController::EvaluateObject(EvaluateObjectRequestView request,
- EvaluateObjectCompleter::Sync &completer) {
- if (request->mode != fuchsia_hardware_acpi::wire::EvaluateObjectMode::kPlainObject) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotSupported);
- return;
- }
-
- if (request->path.get() != "_MUL") {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotFound);
- return;
- }
-
- fidl::Arena arena;
- completer.ReplySuccess(fuchsia_hardware_acpi::wire::EncodedObject());
- // To simulate asynchronous hardware, we post a delayed task and trigger an interrupt when the
- // task is complete.
- async::PostDelayedTask(
- dispatcher_,
- [this]() mutable {
- auto value1 = acpi_multiply::MultiplyArgumentReg::Get(true).ReadFrom(&buffer_.value());
- auto value2 = acpi_multiply::MultiplyArgumentReg::Get(false).ReadFrom(&buffer_.value());
- auto status_reg = acpi_multiply::MultiplyStatusReg::Get().FromValue(0);
- auto result_reg = acpi_multiply::MultiplyResultReg::Get().FromValue(0);
-
- uint32_t result = value1.operand() * value2.operand();
- // Check for overflow
- if (value1.operand() != 0 && result / value1.operand() != value2.operand()) {
- status_reg.set_overflow(true);
- }
- result_reg.set_result(result);
- result_reg.WriteTo(&buffer_.value());
- status_reg.set_finished(true).WriteTo(&buffer_.value());
- zx_status_t status = irq_.trigger(0, zx::clock::get_monotonic());
- if (status != ZX_OK) {
- FDF_SLOG(ERROR, "Failed to trigger interrupt",
- KV("status", zx_status_get_string(status)));
- }
- },
- zx::msec(10));
-}
-
} // namespace acpi_multiply
-FUCHSIA_DRIVER_RECORD_CPP_V1(acpi_multiply::AcpiMultiplyController);
+FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<acpi_multiply::AcpiMultiplyController>);
diff --git a/src/acpi_multiply/controller/acpi_controller.h b/src/acpi_multiply/controller/acpi_controller.h
index 805e390..e01c6e6 100644
--- a/src/acpi_multiply/controller/acpi_controller.h
+++ b/src/acpi_multiply/controller/acpi_controller.h
@@ -5,15 +5,9 @@
#ifndef SRC_ACPI_MULTIPLY_ACPI_CONTROLLER_H_
#define SRC_ACPI_MULTIPLY_ACPI_CONTROLLER_H_
-#include <fidl/fuchsia.driver.framework/cpp/markers.h>
-#include <fidl/fuchsia.driver.framework/cpp/wire_types.h>
-#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
-#include <lib/driver2/logger.h>
-#include <lib/driver2/namespace.h>
-#include <lib/fdf/cpp/dispatcher.h>
-#include <lib/mmio/mmio-buffer.h>
-#include <lib/sys/component/cpp/outgoing_directory.h>
-#include <lib/zx/status.h>
+#include <lib/driver2/driver2_cpp.h>
+
+#include "acpi_server.h"
namespace acpi_multiply {
@@ -24,77 +18,25 @@
// for an interrupt.
// 3. This driver performs the multiplication, writes the result (64-bit) to 0x08
// and triggers an interrupt.
-class AcpiMultiplyController : public fidl::WireServer<fuchsia_hardware_acpi::Device> {
+class AcpiMultiplyController : public driver::DriverBase {
public:
- AcpiMultiplyController(async_dispatcher_t* dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node,
- driver::Namespace ns, driver::Logger logger)
- : dispatcher_(dispatcher),
- outgoing_(component::OutgoingDirectory::Create(dispatcher)),
- ns_(std::move(ns)),
- logger_(std::move(logger)),
- node_(std::move(node)) {}
+ AcpiMultiplyController(driver::DriverStartArgs start_args,
+ fdf::UnownedDispatcher driver_dispatcher)
+ : driver::DriverBase("sample-acpi-controller", std::move(start_args),
+ std::move(driver_dispatcher)) {}
virtual ~AcpiMultiplyController() = default;
- static constexpr const char* Name() { return "sample-acpi-controller"; }
- static zx::status<std::unique_ptr<AcpiMultiplyController>> Start(
- fuchsia_driver_framework::wire::DriverStartArgs& start_args,
- fdf::UnownedDispatcher dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
- driver::Logger logger);
-
- // fuchsia.hardware.acpi/Device:
- void MapInterrupt(MapInterruptRequestView request, MapInterruptCompleter::Sync& completer);
- void GetMmio(GetMmioRequestView request, GetMmioCompleter::Sync& completer);
- void EvaluateObject(EvaluateObjectRequestView request, EvaluateObjectCompleter::Sync& completer);
-
- void GetBusId(GetBusIdCompleter::Sync& completer) { completer.ReplyError(ZX_ERR_BAD_STATE); }
-
- void GetPio(GetPioRequestView request, GetPioCompleter::Sync& completer) {
- completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
- }
- void GetBti(GetBtiRequestView request, GetBtiCompleter::Sync& completer) {
- completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
- }
-
- void InstallNotifyHandler(InstallNotifyHandlerRequestView request,
- InstallNotifyHandlerCompleter::Sync& completer) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
- }
-
- void RemoveNotifyHandler(RemoveNotifyHandlerCompleter::Sync& completer) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
- }
-
- void AcquireGlobalLock(AcquireGlobalLockCompleter::Sync& completer) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
- }
-
- void InstallAddressSpaceHandler(InstallAddressSpaceHandlerRequestView request,
- InstallAddressSpaceHandlerCompleter::Sync& completer) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
- }
-
- void SetWakeDevice(SetWakeDeviceRequestView request, SetWakeDeviceCompleter::Sync& completer) {
- completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
- }
+ zx::status<> Start() override;
private:
- zx::status<> Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir);
+ zx::status<> InitializeServer();
zx::status<> AddChild();
- async_dispatcher_t* const dispatcher_;
- component::OutgoingDirectory outgoing_;
- driver::Namespace ns_;
- driver::Logger logger_;
+ fidl::WireSyncClient<fuchsia_driver_framework::Node> node_;
+ fidl::WireSyncClient<fuchsia_driver_framework::NodeController> controller_;
- zx::interrupt irq_;
-
- std::optional<fdf::MmioBuffer> buffer_;
-
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node_;
- fidl::WireSharedClient<fuchsia_driver_framework::NodeController> controller_;
+ std::shared_ptr<AcpiDeviceServer> server_;
};
} // namespace acpi_multiply
diff --git a/src/acpi_multiply/controller/acpi_server.cc b/src/acpi_multiply/controller/acpi_server.cc
new file mode 100644
index 0000000..2d9e522
--- /dev/null
+++ b/src/acpi_multiply/controller/acpi_server.cc
@@ -0,0 +1,117 @@
+// 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_server.h"
+
+#include <lib/async/cpp/task.h>
+#include <lib/driver2/structured_logger.h>
+#include <lib/zx/clock.h>
+
+#include "registers.h"
+
+namespace acpi_multiply {
+
+// Static
+// Handle incoming connection requests from FIDL clients
+fidl::ServerBindingRef<fuchsia_hardware_acpi::Device> AcpiDeviceServer::BindDeviceClient(
+ std::shared_ptr<AcpiDeviceServer> server_impl, async_dispatcher_t* dispatcher,
+ fidl::ServerEnd<fuchsia_hardware_acpi::Device> request) {
+ // Bind each connection request to the shared instance.
+ return fidl::BindServer(dispatcher, std::move(request), server_impl,
+ std::mem_fn(&AcpiDeviceServer::OnUnbound));
+}
+
+// This method is called when a server connection is torn down.
+void AcpiDeviceServer::OnUnbound(fidl::UnbindInfo info,
+ fidl::ServerEnd<fuchsia_hardware_acpi::Device> server_end) {
+ if (info.is_peer_closed()) {
+ FDF_LOG(DEBUG, "Client disconnected");
+ } else if (!info.is_user_initiated()) {
+ FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
+ }
+}
+
+// Protocol method for `fuchsia.hardware.acpi/Device` to return the requested IRQ.
+void AcpiDeviceServer::MapInterrupt(MapInterruptRequestView request,
+ MapInterruptCompleter::Sync& completer) {
+ if (request->index != 0) {
+ completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
+ return;
+ }
+
+ zx::interrupt clone;
+ zx_status_t status = irq_.duplicate(ZX_RIGHT_SAME_RIGHTS, &clone);
+ if (status != ZX_OK) {
+ completer.ReplyError(status);
+ return;
+ }
+
+ completer.ReplySuccess(std::move(clone));
+}
+
+// Protocol method for `fuchsia.hardware.acpi/Device` to return a requested MMIO region.
+void AcpiDeviceServer::GetMmio(GetMmioRequestView request, GetMmioCompleter::Sync& completer) {
+ if (request->index != 0) {
+ completer.ReplyError(ZX_ERR_OUT_OF_RANGE);
+ return;
+ }
+
+ zx::vmo clone;
+ zx_status_t status = buffer_.get_vmo()->duplicate(ZX_RIGHT_SAME_RIGHTS, &clone);
+ if (status != ZX_OK) {
+ completer.ReplyError(status);
+ return;
+ }
+
+ completer.ReplySuccess(fuchsia_mem::wire::Range{
+ .vmo = std::move(clone),
+ .offset = 0,
+ .size = zx_system_get_page_size(),
+ });
+}
+
+// Protocol method for `fuchsia.hardware.acpi/Device` to interpret an invoke the control method
+// associated with the provided object path.
+void AcpiDeviceServer::EvaluateObject(EvaluateObjectRequestView request,
+ EvaluateObjectCompleter::Sync& completer) {
+ if (request->mode != fuchsia_hardware_acpi::wire::EvaluateObjectMode::kPlainObject) {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotSupported);
+ return;
+ }
+
+ if (request->path.get() != "_MUL") {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotFound);
+ return;
+ }
+
+ fidl::Arena arena;
+ completer.ReplySuccess(fuchsia_hardware_acpi::wire::EncodedObject());
+ // To simulate asynchronous hardware, we post a delayed task and trigger an interrupt when the
+ // task is complete.
+ async::PostDelayedTask(
+ dispatcher_,
+ [this]() mutable {
+ auto value1 = acpi_multiply::MultiplyArgumentReg::Get(true).ReadFrom(&buffer_);
+ auto value2 = acpi_multiply::MultiplyArgumentReg::Get(false).ReadFrom(&buffer_);
+ auto status_reg = acpi_multiply::MultiplyStatusReg::Get().FromValue(0);
+ auto result_reg = acpi_multiply::MultiplyResultReg::Get().FromValue(0);
+
+ uint32_t result = value1.operand() * value2.operand();
+ // Check for overflow
+ if (value1.operand() != 0 && result / value1.operand() != value2.operand()) {
+ status_reg.set_overflow(true);
+ }
+ result_reg.set_result(result);
+ result_reg.WriteTo(&buffer_);
+ status_reg.set_finished(true).WriteTo(&buffer_);
+ zx_status_t status = irq_.trigger(0, zx::clock::get_monotonic());
+ if (status != ZX_OK) {
+ FDF_SLOG(ERROR, "Failed to trigger interrupt",
+ KV("status", zx_status_get_string(status)));
+ }
+ },
+ zx::msec(10));
+}
+
+} // namespace acpi_multiply
diff --git a/src/acpi_multiply/controller/acpi_server.h b/src/acpi_multiply/controller/acpi_server.h
new file mode 100644
index 0000000..df4a0bd
--- /dev/null
+++ b/src/acpi_multiply/controller/acpi_server.h
@@ -0,0 +1,83 @@
+// 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.
+
+#ifndef SRC_ACPI_MULTIPLY_ACPI_SERVER_H_
+#define SRC_ACPI_MULTIPLY_ACPI_SERVER_H_
+
+#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
+#include <lib/driver2/logger.h>
+#include <lib/mmio/mmio-buffer.h>
+
+namespace acpi_multiply {
+
+// FIDL server implementation for the `fuchsia.hardware.acpi/Device` protocol
+class AcpiDeviceServer : public fidl::WireServer<fuchsia_hardware_acpi::Device> {
+ public:
+ AcpiDeviceServer(zx::interrupt irq, fdf::MmioBuffer buffer, driver::Logger& logger,
+ async_dispatcher_t* dispatcher)
+ : irq_(std::move(irq)),
+ buffer_(std::move(buffer)),
+ logger_(logger),
+ dispatcher_(dispatcher) {}
+
+ static fidl::ServerBindingRef<fuchsia_hardware_acpi::Device> BindDeviceClient(
+ std::shared_ptr<AcpiDeviceServer> server_impl, async_dispatcher_t* dispatcher,
+ fidl::ServerEnd<fuchsia_hardware_acpi::Device> request);
+
+ void OnUnbound(fidl::UnbindInfo info, fidl::ServerEnd<fuchsia_hardware_acpi::Device> server_end);
+
+ // fidl::WireServer<fuchsia_hardware_acpi::Device>
+
+ void MapInterrupt(MapInterruptRequestView request,
+ MapInterruptCompleter::Sync& completer) override;
+
+ void GetMmio(GetMmioRequestView request, GetMmioCompleter::Sync& completer) override;
+
+ void EvaluateObject(EvaluateObjectRequestView request,
+ EvaluateObjectCompleter::Sync& completer) override;
+
+ void GetBusId(GetBusIdCompleter::Sync& completer) override {
+ completer.ReplyError(ZX_ERR_BAD_STATE);
+ }
+
+ void GetPio(GetPioRequestView request, GetPioCompleter::Sync& completer) override {
+ completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
+ }
+ void GetBti(GetBtiRequestView request, GetBtiCompleter::Sync& completer) override {
+ completer.ReplyError(ZX_ERR_NOT_SUPPORTED);
+ }
+
+ void InstallNotifyHandler(InstallNotifyHandlerRequestView request,
+ InstallNotifyHandlerCompleter::Sync& completer) override {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
+ }
+
+ void RemoveNotifyHandler(RemoveNotifyHandlerCompleter::Sync& completer) override {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
+ }
+
+ void AcquireGlobalLock(AcquireGlobalLockCompleter::Sync& completer) override {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
+ }
+
+ void InstallAddressSpaceHandler(InstallAddressSpaceHandlerRequestView request,
+ InstallAddressSpaceHandlerCompleter::Sync& completer) override {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
+ }
+
+ void SetWakeDevice(SetWakeDeviceRequestView request,
+ SetWakeDeviceCompleter::Sync& completer) override {
+ completer.ReplyError(fuchsia_hardware_acpi::wire::Status::kNotImplemented);
+ }
+
+ private:
+ zx::interrupt irq_;
+ fdf::MmioBuffer buffer_;
+ driver::Logger& logger_;
+ async_dispatcher_t* dispatcher_;
+};
+
+} // namespace acpi_multiply
+
+#endif // SRC_ACPI_MULTIPLY_ACPI_SERVER_H_
diff --git a/src/acpi_multiply/controller/meta/acpi_controller.cml b/src/acpi_multiply/controller/meta/acpi_controller.cml
index cddfeb7..ab6b620 100644
--- a/src/acpi_multiply/controller/meta/acpi_controller.cml
+++ b/src/acpi_multiply/controller/meta/acpi_controller.cml
@@ -13,14 +13,13 @@
use: [
{ service: 'fuchsia.driver.compat.Service' },
],
- // Provide the ACPI device capability to other components
- // TODO(fxbug.dev/106665): Route as a service capability from the SDK
+ // Provide the ACPI service capability to other components
capabilities: [
- { protocol: 'fuchsia.hardware.acpi.Device' },
+ { service: 'fuchsia.hardware.acpi.Service' },
],
expose: [
{
- protocol: 'fuchsia.hardware.acpi.Device',
+ service: 'fuchsia.hardware.acpi.Service',
from: 'self',
},
],
diff --git a/src/acpi_multiply/driver/BUILD.bazel b/src/acpi_multiply/driver/BUILD.bazel
index ddf2d36..8941d43 100644
--- a/src/acpi_multiply/driver/BUILD.bazel
+++ b/src/acpi_multiply/driver/BUILD.bazel
@@ -4,7 +4,6 @@
load(
"@rules_fuchsia//fuchsia:defs.bzl",
- "fuchsia_cc_binary",
"fuchsia_component_manifest",
"fuchsia_driver_bind_bytecode",
"fuchsia_driver_component",
@@ -28,20 +27,17 @@
"acpi_multiply.h",
"multiplier.cc",
"multiplier.h",
+ "multiply_server.cc",
+ "multiply_server.h",
],
linkshared = True,
deps = [
"//src/acpi_multiply/fidl:fuchsia.examples.acpi.multiply_cc",
"//src/acpi_multiply/lib",
"@fuchsia_sdk//fidl/fuchsia.hardware.acpi:fuchsia.hardware.acpi_llcpp_cc",
- "@fuchsia_sdk//fidl/zx:zx_cc",
"@fuchsia_sdk//pkg/async-cpp",
- "@fuchsia_sdk//pkg/mmio",
- "@fuchsia_sdk//pkg/hwreg",
"@fuchsia_sdk//pkg/driver2_cpp",
- "@fuchsia_sdk//pkg/fidl_cpp_wire",
- "@fuchsia_sdk//pkg/sys_component_cpp",
- "@fuchsia_sdk//pkg/zx",
+ "@fuchsia_sdk//pkg/mmio",
],
)
diff --git a/src/acpi_multiply/driver/acpi_multiply.cc b/src/acpi_multiply/driver/acpi_multiply.cc
index 5b10eab..cb2fe02 100644
--- a/src/acpi_multiply/driver/acpi_multiply.cc
+++ b/src/acpi_multiply/driver/acpi_multiply.cc
@@ -4,96 +4,18 @@
#include "acpi_multiply.h"
+#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <lib/async/cpp/task.h>
+#include <lib/driver2/service_client.h>
-namespace {
-
-// FIDL server implementation for the `fuchsia.examples.acpi.multiply/Device` protocol
-class AcpiMultiplyServer : public fidl::WireServer<fuchsia_examples_acpi_multiply::Device> {
- public:
- explicit AcpiMultiplyServer(driver::Namespace& ns, async_dispatcher_t* dispatcher,
- std::weak_ptr<acpi_multiply::AcpiMultiplier> multiplier)
- : multiplier_(multiplier) {
- auto logger_result = driver::Logger::Create(ns, dispatcher, "acpi-multiply-server");
- ZX_ASSERT(logger_result.is_ok());
- logger_ = std::move(*logger_result);
- }
-
- // Handle incoming connection requests from FIDL clients
- static fidl::ServerBindingRef<fuchsia_examples_acpi_multiply::Device> BindDeviceClient(
- driver::Namespace& ns, async_dispatcher_t* dispatcher,
- std::weak_ptr<acpi_multiply::AcpiMultiplier> multiplier,
- fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> request) {
- // Bind each connection request to a unique FIDL server instance
- auto server_impl = std::make_unique<AcpiMultiplyServer>(ns, dispatcher, multiplier);
- return fidl::BindServer(dispatcher, std::move(request), std::move(server_impl),
- std::mem_fn(&AcpiMultiplyServer::OnUnbound));
- }
-
- // This method is called when a server connection is torn down.
- void OnUnbound(fidl::UnbindInfo info,
- fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> server_end) {
- if (info.is_peer_closed()) {
- FDF_LOG(DEBUG, "Client disconnected");
- } else if (!info.is_user_initiated()) {
- FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
- }
- }
-
- void Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer) override;
-
- private:
- driver::Logger logger_;
- std::weak_ptr<acpi_multiply::AcpiMultiplier> multiplier_;
-};
-
-// Protocol method in `fuchsia.examples.acpi.multiply` to execute a multiply operation
-void AcpiMultiplyServer::Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer) {
- auto multiplier = multiplier_.lock();
- if (!multiplier) {
- FDF_LOG(ERROR, "Unable to access ACPI resources.");
- completer.ReplyError(ZX_ERR_BAD_STATE);
- return;
- }
-
- multiplier->QueueMultiplyOperation(acpi_multiply::AcpiMultiplier::Operation{
- .a = request->a,
- .b = request->b,
- .callback =
- [completer = completer.ToAsync()](
- zx::status<acpi_multiply::AcpiMultiplier::MultiplyResult> status) mutable {
- if (status.is_error()) {
- completer.ReplyError(status.error_value());
- return;
- }
-
- acpi_multiply::AcpiMultiplier::MultiplyResult result = status.value();
- completer.ReplySuccess(result.value, result.overflow);
- },
- });
-}
-
-} // namespace
+#include "multiply_server.h"
namespace acpi_multiply {
-zx::status<std::unique_ptr<AcpiMultiplyDriver>> AcpiMultiplyDriver::Start(
- fuchsia_driver_framework::wire::DriverStartArgs& start_args, fdf::UnownedDispatcher dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
- driver::Logger logger) {
- auto driver = std::make_unique<AcpiMultiplyDriver>(
- 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));
-}
-
-zx::status<> AcpiMultiplyDriver::Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir) {
+zx::status<> AcpiMultiplyDriver::Start() {
// Connect to the ACPI protocol exposed by the parent driver.
- auto client_endpoint = ns_.Connect<fuchsia_hardware_acpi::Device>();
+ 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();
@@ -101,7 +23,8 @@
auto acpi_client = fidl::WireSyncClient(std::move(*client_endpoint));
// Initialize ACPI hardware resources
- multiplier_ = std::make_shared<AcpiMultiplier>(ns_, dispatcher_, std::move(acpi_client));
+ multiplier_ =
+ std::make_shared<AcpiMultiplier>(logger_, async_dispatcher(), std::move(acpi_client));
auto init_result = multiplier_->SetupMmioAndInterrupts();
if (init_result.is_error()) {
FDF_SLOG(ERROR, "Failed to initialize ACPI resources.",
@@ -111,40 +34,36 @@
// Serve the fuchsia.examples.acpi.multiply/Device protocol to clients through the
// fuchsia.examples.acpi.multiply/Service wrapper.
- component::ServiceHandler handler;
+ 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(ns_, dispatcher_, multiplier_, std::move(request));
+ AcpiMultiplyServer::BindDeviceClient(logger_, async_dispatcher(), multiplier_,
+ std::move(request));
});
ZX_ASSERT(result.is_ok());
- result = outgoing_.AddService<fuchsia_examples_acpi_multiply::Service>(std::move(handler));
+ 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();
}
- auto status = outgoing_.Serve(std::move(outgoing_dir));
- if (status.is_error()) {
- FDF_SLOG(ERROR, "Failed to serve outgoing directory", KV("status", status.status_string()));
- return status.take_error();
- }
-
// This is not strictly necessary, but it does a multiplication to prove that the driver
// behaves as expected.
- async::PostTask(dispatcher_, [this]() {
+ async::PostTask(async_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>(ns_, dispatcher_, multiplier_);
- fidl::BindServer(dispatcher_, std::move(endpoints->server), std::move(server_impl),
+ auto server_impl = std::make_unique<AcpiMultiplyServer>(logger_, multiplier_);
+ fidl::BindServer(async_dispatcher(), std::move(endpoints->server), std::move(server_impl),
std::mem_fn(&AcpiMultiplyServer::OnUnbound));
- client_.Bind(std::move(endpoints->client), dispatcher_);
+ client_.Bind(std::move(endpoints->client), async_dispatcher());
// Do the multiply
client_->Multiply(UINT32_MAX, 9)
.Then([this](fidl::WireUnownedResult<fuchsia_examples_acpi_multiply::Device::Multiply>&
@@ -179,4 +98,4 @@
} // namespace acpi_multiply
-FUCHSIA_DRIVER_RECORD_CPP_V1(acpi_multiply::AcpiMultiplyDriver);
+FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<acpi_multiply::AcpiMultiplyDriver>);
diff --git a/src/acpi_multiply/driver/acpi_multiply.h b/src/acpi_multiply/driver/acpi_multiply.h
index 4bd8e2e..40c4887 100644
--- a/src/acpi_multiply/driver/acpi_multiply.h
+++ b/src/acpi_multiply/driver/acpi_multiply.h
@@ -5,54 +5,24 @@
#ifndef SRC_ACPI_MULTIPLY_ACPI_MULTIPLY_H_
#define SRC_ACPI_MULTIPLY_ACPI_MULTIPLY_H_
-#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <fidl/fuchsia.examples.acpi.multiply/cpp/wire.h>
-#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
-#include <lib/driver2/logger.h>
-#include <lib/driver2/namespace.h>
-#include <lib/driver2/record_cpp.h>
-#include <lib/driver2/structured_logger.h>
-#include <lib/fdf/cpp/dispatcher.h>
-#include <lib/sys/component/cpp/outgoing_directory.h>
-#include <lib/zx/status.h>
+#include <lib/driver2/driver2_cpp.h>
#include "multiplier.h"
namespace acpi_multiply {
// Sample driver for a virtual "multiplier" device described using ACPI.
-class AcpiMultiplyDriver {
+class AcpiMultiplyDriver : public driver::DriverBase {
public:
- AcpiMultiplyDriver(async_dispatcher_t* dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node,
- driver::Namespace ns, driver::Logger logger)
- : dispatcher_(dispatcher),
- node_(std::move(node)),
- outgoing_(component::OutgoingDirectory::Create(dispatcher)),
- ns_(std::move(ns)),
- logger_(std::move(logger)) {}
+ AcpiMultiplyDriver(driver::DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher)
+ : driver::DriverBase("acpi-multiply", std::move(start_args), std::move(driver_dispatcher)) {}
virtual ~AcpiMultiplyDriver() = default;
- static constexpr const char* Name() { return "acpi-multiply"; }
-
- static zx::status<std::unique_ptr<AcpiMultiplyDriver>> Start(
- fuchsia_driver_framework::wire::DriverStartArgs& start_args,
- fdf::UnownedDispatcher dispatcher,
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node, driver::Namespace ns,
- driver::Logger logger);
+ zx::status<> Start() override;
private:
- zx::status<> Run(fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir);
-
- async_dispatcher_t* const dispatcher_;
-
- fidl::WireSharedClient<fuchsia_driver_framework::Node> node_;
-
- component::OutgoingDirectory outgoing_;
- driver::Namespace ns_;
- driver::Logger logger_;
-
std::shared_ptr<AcpiMultiplier> multiplier_;
// Used by the self-test.
diff --git a/src/acpi_multiply/driver/meta/acpi_multiply.cml b/src/acpi_multiply/driver/meta/acpi_multiply.cml
index 07aba91..a6f8154 100644
--- a/src/acpi_multiply/driver/meta/acpi_multiply.cml
+++ b/src/acpi_multiply/driver/meta/acpi_multiply.cml
@@ -10,10 +10,10 @@
binary: 'lib/libacpi_multiply.so',
bind: 'meta/bind/acpi_multiply.bindbc'
},
- // Consume the ACPI device capability from the parent
+ // Consume the ACPI service capability from the parent
use: [
- { protocol: 'fuchsia.hardware.acpi.Device' },
{ service: 'fuchsia.driver.compat.Service' },
+ { service: 'fuchsia.hardware.acpi.Service' },
],
// Provide the multiply device capability to other components
capabilities: [
diff --git a/src/acpi_multiply/driver/multiplier.h b/src/acpi_multiply/driver/multiplier.h
index 8ef4504..4e0bc87 100644
--- a/src/acpi_multiply/driver/multiplier.h
+++ b/src/acpi_multiply/driver/multiplier.h
@@ -7,9 +7,7 @@
#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <lib/async/cpp/irq.h>
-#include <lib/driver2/logger.h>
-#include <lib/driver2/namespace.h>
-#include <lib/driver2/structured_logger.h>
+#include <lib/driver2/driver2_cpp.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/interrupt.h>
@@ -20,13 +18,9 @@
// Invokes ACPI methods using a fuchsia.hardware.acpi client.
class AcpiMultiplier {
public:
- explicit AcpiMultiplier(driver::Namespace& ns, async_dispatcher_t* dispatcher,
+ explicit AcpiMultiplier(driver::Logger& logger, async_dispatcher_t* dispatcher,
fidl::WireSyncClient<fuchsia_hardware_acpi::Device> acpi)
- : dispatcher_(dispatcher), acpi_(std::move(acpi)) {
- auto logger_result = driver::Logger::Create(ns, dispatcher, "acpi-multiplier");
- ZX_ASSERT(logger_result.is_ok());
- logger_ = std::move(*logger_result);
- }
+ : logger_(logger), dispatcher_(dispatcher), acpi_(std::move(acpi)) {}
zx::status<> SetupMmioAndInterrupts();
@@ -53,7 +47,7 @@
void DoMultiply(Operation operation);
- driver::Logger logger_;
+ driver::Logger& logger_;
async_dispatcher_t* const dispatcher_;
std::optional<fdf::MmioBuffer> mmio_;
diff --git a/src/acpi_multiply/driver/multiply_server.cc b/src/acpi_multiply/driver/multiply_server.cc
new file mode 100644
index 0000000..2bcc91d
--- /dev/null
+++ b/src/acpi_multiply/driver/multiply_server.cc
@@ -0,0 +1,57 @@
+// 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 "multiply_server.h"
+
+namespace acpi_multiply {
+
+// Static
+// Handle incoming connection requests from FIDL clients
+fidl::ServerBindingRef<fuchsia_examples_acpi_multiply::Device> AcpiMultiplyServer::BindDeviceClient(
+ driver::Logger& logger, async_dispatcher_t* dispatcher,
+ std::weak_ptr<AcpiMultiplier> multiplier,
+ fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> request) {
+ // Bind each connection request to a unique FIDL server instance
+ auto server_impl = std::make_unique<AcpiMultiplyServer>(logger, multiplier);
+ return fidl::BindServer(dispatcher, std::move(request), std::move(server_impl),
+ std::mem_fn(&AcpiMultiplyServer::OnUnbound));
+}
+
+// This method is called when a server connection is torn down.
+void AcpiMultiplyServer::OnUnbound(
+ fidl::UnbindInfo info, fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> server_end) {
+ if (info.is_peer_closed()) {
+ FDF_LOG(DEBUG, "Client disconnected");
+ } else if (!info.is_user_initiated()) {
+ FDF_LOG(ERROR, "Client connection unbound: %s", info.status_string());
+ }
+}
+
+// Protocol method in `fuchsia.examples.acpi.multiply` to execute a multiply operation
+void AcpiMultiplyServer::Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer) {
+ auto multiplier = multiplier_.lock();
+ if (!multiplier) {
+ FDF_LOG(ERROR, "Unable to access ACPI resources.");
+ completer.ReplyError(ZX_ERR_BAD_STATE);
+ return;
+ }
+
+ multiplier->QueueMultiplyOperation(AcpiMultiplier::Operation{
+ .a = request->a,
+ .b = request->b,
+ .callback =
+ [completer =
+ completer.ToAsync()](zx::status<AcpiMultiplier::MultiplyResult> status) mutable {
+ if (status.is_error()) {
+ completer.ReplyError(status.error_value());
+ return;
+ }
+
+ AcpiMultiplier::MultiplyResult result = status.value();
+ completer.ReplySuccess(result.value, result.overflow);
+ },
+ });
+}
+
+} // namespace acpi_multiply
diff --git a/src/acpi_multiply/driver/multiply_server.h b/src/acpi_multiply/driver/multiply_server.h
new file mode 100644
index 0000000..d1ed5ad
--- /dev/null
+++ b/src/acpi_multiply/driver/multiply_server.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef SRC_ACPI_MULTIPLY_MULTIPLY_SERVER_H_
+#define SRC_ACPI_MULTIPLY_MULTIPLY_SERVER_H_
+
+#include <fidl/fuchsia.examples.acpi.multiply/cpp/wire.h>
+#include <lib/driver2/logger.h>
+
+#include "multiplier.h"
+
+namespace acpi_multiply {
+
+// FIDL server implementation for the `fuchsia.examples.acpi.multiply/Device` protocol
+class AcpiMultiplyServer : public fidl::WireServer<fuchsia_examples_acpi_multiply::Device> {
+ public:
+ AcpiMultiplyServer(driver::Logger& logger, std::weak_ptr<AcpiMultiplier> multiplier)
+ : logger_(logger), multiplier_(multiplier) {}
+
+ static fidl::ServerBindingRef<fuchsia_examples_acpi_multiply::Device> BindDeviceClient(
+ driver::Logger& logger, async_dispatcher_t* dispatcher,
+ std::weak_ptr<AcpiMultiplier> multiplier,
+ fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> request);
+
+ void OnUnbound(fidl::UnbindInfo info,
+ fidl::ServerEnd<fuchsia_examples_acpi_multiply::Device> server_end);
+
+ // fidl::WireServer<fuchsia_examples_acpi_multiply::Device>
+
+ void Multiply(MultiplyRequestView request, MultiplyCompleter::Sync& completer) override;
+
+ private:
+ driver::Logger& logger_;
+ std::weak_ptr<AcpiMultiplier> multiplier_;
+};
+
+} // namespace acpi_multiply
+
+#endif /* SRC_ACPI_MULTIPLY_MULTIPLY_SERVER_H_ */
diff --git a/src/acpi_multiply/lib/BUILD.bazel b/src/acpi_multiply/lib/BUILD.bazel
index 65726c0..3182b4d 100644
--- a/src/acpi_multiply/lib/BUILD.bazel
+++ b/src/acpi_multiply/lib/BUILD.bazel
@@ -7,4 +7,5 @@
hdrs = ["include/registers.h"],
includes = ["include"],
visibility = ["//visibility:public"],
+ deps = ["@fuchsia_sdk//pkg/hwreg"],
)