blob: 685090933b6f45f079ac64d3741bae576b6de3a3 [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.device.fs/cpp/wire.h>
#include <fidl/fuchsia.driver.compat/cpp/wire.h>
#include <fidl/fuchsia.driver.framework/cpp/wire.h>
#include <fidl/fuchsia.hardware.demo/cpp/wire.h>
#include <lib/driver2/namespace.h>
#include <lib/driver2/record_cpp.h>
#include <lib/driver2/start_args.h>
#include <lib/driver2/structured_logger.h>
#include <lib/sys/component/llcpp/outgoing_directory.h>
#include <zircon/errors.h>
namespace fdf2 = fuchsia_driver_framework;
namespace fio = fuchsia_io;
namespace {
class DemoNumber : public fidl::WireServer<fuchsia_hardware_demo::Demo> {
public:
DemoNumber(async_dispatcher_t* dispatcher, fidl::WireSharedClient<fdf2::Node> node,
driver::Namespace ns, component::OutgoingDirectory outgoing, driver::Logger logger)
: dispatcher_(dispatcher),
outgoing_(std::move(outgoing)),
node_(std::move(node)),
ns_(std::move(ns)),
logger_(std::move(logger)) {}
static constexpr const char* Name() { return "demo_number"; }
static zx::status<std::unique_ptr<DemoNumber>> Start(fdf2::wire::DriverStartArgs& start_args,
fdf::UnownedDispatcher dispatcher,
fidl::WireSharedClient<fdf2::Node> node,
driver::Namespace ns,
driver::Logger logger) {
auto outgoing = component::OutgoingDirectory::Create(dispatcher->async_dispatcher());
auto driver =
std::make_unique<DemoNumber>(dispatcher->async_dispatcher(), std::move(node), std::move(ns),
std::move(outgoing), 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));
}
private:
zx::status<> Run(fidl::ServerEnd<fio::Directory> outgoing_dir) {
// Connect to DevfsExporter.
auto exporter = ns_.Connect<fuchsia_device_fs::Exporter>();
if (exporter.status_value() != ZX_OK) {
return exporter.take_error();
}
exporter_ = fidl::WireClient(std::move(*exporter), dispatcher_);
// Connect to parent.
auto parent = ns_.Connect<fuchsia_driver_compat::Device>(
"/svc/fuchsia.driver.compat.Service/default/device");
if (parent.status_value() != ZX_OK) {
return parent.take_error();
}
auto result = fidl::WireCall(*parent)->GetTopologicalPath();
if (!result.ok()) {
return zx::error(result.status());
}
std::string path(result.value().path.data(), result.value().path.size());
auto status = outgoing_.AddProtocol<fuchsia_hardware_demo::Demo>(this, Name());
if (status.status_value() != ZX_OK) {
return status;
}
path.append("/");
path.append(Name());
FDF_LOG(INFO, "Exporting device to: %s", path.data());
// Serve a connection to outgoing.
auto endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
if (endpoints.is_error()) {
return endpoints.take_error();
}
{
auto status = outgoing_.Serve(std::move(endpoints->server));
if (status.is_error()) {
return status.take_error();
}
}
// Export our protocol.
exporter_
->Export(std::move(endpoints->client),
fidl::StringView::FromExternal(std::string("svc/").append(Name())),
fidl::StringView::FromExternal(path), 0)
.Then([this](fidl::WireUnownedResult<fuchsia_device_fs::Exporter::Export>& result) {
if (!result.ok()) {
FDF_LOG(ERROR, "Exporting failed with: %s", result.status_string());
}
});
return outgoing_.Serve(std::move(outgoing_dir));
}
void GetNumber(GetNumberRequestView request, GetNumberCompleter::Sync& completer) override {
completer.Reply(current_number);
current_number += 1;
}
async_dispatcher_t* dispatcher_;
component::OutgoingDirectory outgoing_;
fidl::WireSharedClient<fdf2::Node> node_;
driver::Namespace ns_;
driver::Logger logger_;
fidl::WireClient<fuchsia_device_fs::Exporter> exporter_;
std::string parent_topo_path_;
uint32_t current_number = 0;
};
} // namespace
FUCHSIA_DRIVER_RECORD_CPP_V1(DemoNumber);