blob: 86aabab9a4ba8e60a56568f07f47ad04d4bf0738 [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 <fidl/fuchsia.nodegroup.test/cpp/wire.h>
#include <lib/async/cpp/task.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/component/cpp/driver_export.h>
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace ft = fuchsia_nodegroup_test;
namespace {
class LeafDriver : public fdf::DriverBase {
public:
LeafDriver(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: fdf::DriverBase("leaf", std::move(start_args), std::move(driver_dispatcher)) {}
zx::result<> Start() override {
auto result = async::PostTask(dispatcher(), [&]() { RunAsync(); });
if (result == ZX_OK) {
return zx::ok();
}
return zx::error(result);
}
void RunAsync() {
auto connect_result = incoming()->Connect<ft::Waiter>();
if (connect_result.is_error()) {
FDF_LOG(ERROR, "Failed to start leaf driver: %s", connect_result.status_string());
node().reset();
return;
}
const fidl::WireSharedClient<ft::Waiter> client{std::move(connect_result.value()),
dispatcher()};
auto work_result = DoWork(client);
if (work_result.is_error()) {
FDF_LOG(ERROR, "DoWork was not successful: %s", work_result.status_string());
return;
}
FDF_LOG(INFO, "Completed RunAsync successfully.");
}
private:
zx::result<uint32_t> GetNumber(std::string_view instance) {
auto device = incoming()->Connect<ft::Service::Device>(instance);
if (device.status_value() != ZX_OK) {
FDF_LOG(WARNING, "Failed to connect to %s: %s", instance.data(), device.status_string());
return device.take_error();
}
auto result = fidl::WireCall(*device)->GetNumber();
if (result.status() != ZX_OK) {
FDF_LOG(WARNING, "Failed to call number on %s: %s", instance.data(),
result.lossy_description());
return zx::error(result.status());
}
return zx::ok(result.value().number);
}
zx::result<> DoWork(const fidl::WireSharedClient<ft::Waiter>& waiter) {
// Check the left device.
auto number = GetNumber("left");
if (number.is_error()) {
[[maybe_unused]] auto result = waiter->Ack(number.error_value());
return zx::ok();
}
if (*number != 1) {
FDF_LOG(ERROR, "Wrong number for left: expecting 1, saw %d", *number);
[[maybe_unused]] auto result = waiter->Ack(ZX_ERR_INTERNAL);
return zx::ok();
}
// Check the right device.
number = GetNumber("right");
if (number.is_error()) {
[[maybe_unused]] auto result = waiter->Ack(number.error_value());
return zx::ok();
}
if (*number != 2) {
FDF_LOG(ERROR, "Wrong number for right: expecting 2, saw %d", *number);
[[maybe_unused]] auto result = waiter->Ack(ZX_ERR_INTERNAL);
return zx::ok();
}
// Check the optional device.
number = GetNumber("opt");
if (number.is_error()) {
FDF_LOG(INFO, "No 'opt' parent.");
} else if (*number != 3) {
FDF_LOG(ERROR, "Wrong number for opt: expecting 3, saw %d", *number);
[[maybe_unused]] auto result = waiter->Ack(ZX_ERR_INTERNAL);
return zx::ok();
}
// Check the default device (which is the left device).
number = GetNumber("default");
if (number.is_error()) {
[[maybe_unused]] auto result = waiter->Ack(number.error_value());
return zx::ok();
}
if (*number != 1) {
FDF_LOG(ERROR, "Wrong number for default: expecting 1, saw %d", *number);
[[maybe_unused]] auto result = waiter->Ack(ZX_ERR_INTERNAL);
return zx::ok();
}
[[maybe_unused]] auto result = waiter->Ack(ZX_OK);
return zx::ok();
}
};
} // namespace
FUCHSIA_DRIVER_EXPORT(LeafDriver);