blob: 538834cae2dc761784b2811a37426a7c527e1dea [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 "src/devices/lib/acpi/object.h"
#include "util.h"
namespace acpi {
zx::status<fidl::ClientEnd<fuchsia_hardware_acpi::Device>> Client::Connect(zx_device_t* parent) {
auto endpoints = fidl::CreateEndpoints<fuchsia_hardware_acpi::Device>();
if (endpoints.is_error()) {
return endpoints.take_error();
}
zx_status_t result;
if (device_get_fragment_count(parent) == 0) {
result = device_connect_fidl_protocol(
parent, fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>,
endpoints->server.TakeChannel().release());
} else {
result = device_connect_fragment_fidl_protocol(
parent, "acpi", fidl::DiscoverableProtocolName<fuchsia_hardware_acpi::Device>,
endpoints->server.TakeChannel().release());
}
if (result != ZX_OK) {
return zx::error(result);
}
return zx::ok(std::move(endpoints->client));
}
zx::status<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::status<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;
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));
int argc = 3;
if (params != std::nullopt) {
args[3] = params.value();
argc++;
}
auto result = client_->EvaluateObject(
"_DSM", fuchsia_hardware_acpi::wire::EvaluateObjectMode::kPlainObject,
fidl::VectorView<fuchsia_hardware_acpi::wire::Object>::FromExternal(args.data(), argc));
if (!result.ok()) {
return zx::error(result.status());
}
if (result->is_error()) {
return zx::ok(Object(result->error_value()));
}
if (!result->value()->result.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(result->value()->result.object()));
}
} // namespace acpi