blob: a6a705b807a39c8cc4fe2b588bedc8d8636e8802 [file] [log] [blame]
// Copyright 2021 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 "src/devices/lib/acpi/client.h"
#include <fidl/fuchsia.hardware.acpi/cpp/wire.h>
#include <lib/ddk/debug.h>
#include <lib/ddk/device.h>
#include <lib/ddk/driver.h>
#include <zircon/types.h>
#include <ddktl/device.h>
#include "src/devices/lib/acpi/object.h"
#include "util.h"
namespace acpi {
zx::result<fidl::ClientEnd<fuchsia_hardware_acpi::Device>> Client::Connect(zx_device_t* parent) {
zx::result result =
ddk::Device<void>::DdkConnectFidlProtocol<fuchsia_hardware_acpi::Service::Device>(parent);
if (result.is_error()) {
result =
ddk::Device<void>::DdkConnectFragmentFidlProtocol<fuchsia_hardware_acpi::Service::Device>(
parent, "acpi");
}
return result;
}
zx::result<Client> Client::Create(zx_device_t* parent) {
auto end = Connect(parent);
if (end.is_error()) {
return end.take_error();
}
fidl::WireSyncClient<fuchsia_hardware_acpi::Device> wire_client(std::move(end.value()));
return zx::ok(Client(std::move(wire_client)));
}
Client Client::Create(fidl::WireSyncClient<fuchsia_hardware_acpi::Device> client) {
return Client(std::move(client));
}
zx::result<Object> Client::CallDsm(Uuid uuid, uint64_t revision, uint64_t func_index,
std::optional<fuchsia_hardware_acpi::wire::Object> params) {
std::array<fuchsia_hardware_acpi::wire::Object, 4> args;
fidl::Arena arena;
auto uuid_buf = fidl::VectorView<uint8_t>::FromExternal(uuid.bytes, kUuidBytes);
args[0] = fuchsia_hardware_acpi::wire::Object::WithBufferVal(
fidl::ObjectView<fidl::VectorView<uint8_t>>::FromExternal(&uuid_buf));
args[1] = fuchsia_hardware_acpi::wire::Object::WithIntegerVal(
fidl::ObjectView<uint64_t>::FromExternal(&revision));
args[2] = fuchsia_hardware_acpi::wire::Object::WithIntegerVal(
fidl::ObjectView<uint64_t>::FromExternal(&func_index));
if (params != std::nullopt) {
args[3] = params.value();
} else {
args[3] = fuchsia_hardware_acpi::wire::Object::WithPackageVal(
arena, fuchsia_hardware_acpi::wire::ObjectList());
}
auto result = client_->EvaluateObject(
"_DSM", fuchsia_hardware_acpi::wire::EvaluateObjectMode::kPlainObject,
fidl::VectorView<fuchsia_hardware_acpi::wire::Object>::FromExternal(args));
if (!result.ok()) {
return zx::error(result.status());
}
if (result->is_error()) {
return zx::ok(Object(result->error_value()));
}
fidl::WireOptional<fuchsia_hardware_acpi::wire::EncodedObject>& maybe_encoded =
result->value()->result;
if (!maybe_encoded.has_value() || !maybe_encoded->is_object()) {
// We called EvaluateObject with mode == PlainObject, so don't expect anything else back.
return zx::error(ZX_ERR_INTERNAL);
}
return zx::ok(Object(maybe_encoded->object()));
}
} // namespace acpi