blob: a06a4f0a0ba696ae8b615f5e19f571db86d41fdb [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.composite.test/cpp/wire.h>
#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <lib/async/cpp/executor.h>
#include <lib/driver2/logger.h>
#include <lib/driver2/namespace.h>
#include <lib/driver2/promise.h>
#include <lib/driver2/record_cpp.h>
#include <lib/fpromise/scope.h>
namespace fdf {
using namespace fuchsia_driver_framework;
} // namespace fdf
namespace ft = fuchsia_composite_test;
using fpromise::ok;
using fpromise::result;
namespace {
class LeafDriver {
public:
LeafDriver(async_dispatcher_t* dispatcher, fidl::WireSharedClient<fdf::Node> node,
driver::Namespace ns, driver::Logger logger)
: dispatcher_(dispatcher),
executor_(dispatcher),
node_(std::move(node)),
ns_(std::move(ns)),
logger_(std::move(logger)) {}
static constexpr const char* Name() { return "leaf"; }
static zx::status<std::unique_ptr<LeafDriver>> Start(fdf::wire::DriverStartArgs& start_args,
fdf::UnownedDispatcher dispatcher,
fidl::WireSharedClient<fdf::Node> node,
driver::Namespace ns,
driver::Logger logger) {
auto driver = std::make_unique<LeafDriver>(dispatcher->async_dispatcher(), std::move(node),
std::move(ns), std::move(logger));
driver->Run();
return zx::ok(std::move(driver));
}
private:
void Run() {
// Start the driver.
auto task = driver::Connect<ft::Waiter>(ns_, dispatcher_)
.and_then(fit::bind_member(this, &LeafDriver::DoWork))
.or_else(fit::bind_member(this, &LeafDriver::UnbindNode))
.wrap_with(scope_);
executor_.schedule_task(std::move(task));
}
zx::status<uint32_t> ConnectToDeviceAndGetNumber(std::string path) {
auto device = ns_.Connect<ft::Device>(path);
if (device.status_value() != ZX_OK) {
FDF_LOG(ERROR, "Failed to connect to %s: %s", path.data(), device.status_string());
return device.take_error();
}
auto result = fidl::WireCall(*device)->GetNumber();
if (result.status() != ZX_OK) {
FDF_LOG(ERROR, "Failed to call number on %s: %s", path.data(), result.lossy_description());
return zx::error(result.status());
}
return zx::ok(result.value().number);
}
result<void, zx_status_t> DoWork(const fidl::WireSharedClient<ft::Waiter>& waiter) {
// Check the left device.
auto number = ConnectToDeviceAndGetNumber("/svc/fuchsia.composite.test.Service/left/device");
if (number.is_error()) {
__UNUSED auto result = waiter->Ack(number.error_value());
return ok();
}
if (*number != 1) {
FDF_LOG(ERROR, "Wrong number for left: expecting 1, saw %d", *number);
__UNUSED auto result = waiter->Ack(ZX_ERR_INTERNAL);
return ok();
}
// Check the right device.
number = ConnectToDeviceAndGetNumber("/svc/fuchsia.composite.test.Service/right/device");
if (number.is_error()) {
__UNUSED auto result = waiter->Ack(number.error_value());
return ok();
}
if (*number != 2) {
FDF_LOG(ERROR, "Wrong number for right: expecting 2, saw %d", *number);
__UNUSED auto result = waiter->Ack(ZX_ERR_INTERNAL);
return ok();
}
// Check the default device (which is the left device).
number = ConnectToDeviceAndGetNumber("/svc/fuchsia.composite.test.Service/default/device");
if (number.is_error()) {
__UNUSED auto result = waiter->Ack(number.error_value());
return ok();
}
if (*number != 1) {
FDF_LOG(ERROR, "Wrong number for default: expecting 1, saw %d", *number);
__UNUSED auto result = waiter->Ack(ZX_ERR_INTERNAL);
return ok();
}
__UNUSED auto result = waiter->Ack(ZX_OK);
return ok();
}
result<> UnbindNode(const zx_status_t& status) {
FDF_LOG(ERROR, "Failed to start leaf driver: %s", zx_status_get_string(status));
node_.AsyncTeardown();
return ok();
}
async_dispatcher_t* const dispatcher_;
async::Executor executor_;
fidl::WireSharedClient<fdf::Node> node_;
driver::Namespace ns_;
driver::Logger logger_;
// NOTE: Must be the last member.
fpromise::scope scope_;
};
} // namespace
FUCHSIA_DRIVER_RECORD_CPP_V1(LeafDriver);