blob: b30a1ccc39b12e251b36b42ec44a09072f631f64 [file] [log] [blame]
// Copyright 2023 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 "driver.h"
#include <fidl/fuchsia.hardware.powersource/cpp/natural_types.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/component/cpp/driver_export.h>
#include <lib/driver/component/cpp/node_add_args.h>
#include <lib/driver/devfs/cpp/connector.h>
#include <lib/driver/logging/cpp/structured_logger.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/fit/function.h>
#include <utility>
#include "power_source_state.h"
namespace fake_powersource {
Driver::Driver(fdf::DriverStartArgs start_args,
fdf::UnownedSynchronizedDispatcher driver_dispatcher)
: DriverBase("fake-powersource", std::move(start_args), std::move(driver_dispatcher)),
devfs_connector_source_battery_(fit::bind_member<&Driver::ServeBattery>(this)),
devfs_connector_sim_battery_(fit::bind_member<&Driver::ServeSimulatorBattery>(this)),
protocol_server_battery_(fake_data_battery_),
simulator_server_battery_(fake_data_battery_),
devfs_connector_source_ac_(fit::bind_member<&Driver::ServeAc>(this)),
devfs_connector_sim_ac_(fit::bind_member<&Driver::ServeSimulatorAc>(this)),
protocol_server_ac_(fake_data_ac_),
simulator_server_ac_(fake_data_ac_) {}
zx::result<> Driver::Start() {
node_.Bind(std::move(node()));
auto result = AddDriverAndControl("fake-battery", "battery-source-simulator",
devfs_connector_source_battery_, devfs_connector_sim_battery_);
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add fake battery driver and its control",
KV("status", result.status_string()));
return result.take_error();
}
result = AddDriverAndControl("fake-ac", "ac-source-simulator", devfs_connector_source_ac_,
devfs_connector_sim_ac_);
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add fake ac driver and its control",
KV("status", result.status_string()));
return result.take_error();
}
return zx::ok();
}
template <typename A, typename B>
zx::result<> Driver::AddDriverAndControl(std::string_view driver_node_name,
std::string_view sim_node_name,
driver_devfs::Connector<A>& driver_devfs_connector,
driver_devfs::Connector<B>& sim_devfs_connector) {
auto result = AddChild(driver_node_name, "power", driver_devfs_connector);
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add child node fake battery", KV("status", result.status_string()));
return result.take_error();
}
// (TODO:https://fxbug.dev/42081644) To allow the power-simulator to be found in
// /dev/class/power-simulator, a line needs to be added to src/lib/ddk/include/lib/ddk/protodefs.h
result = AddChild(sim_node_name, "power-sim", sim_devfs_connector);
if (result.is_error()) {
FDF_SLOG(ERROR, "Failed to add child node battery simulator",
KV("status", result.status_string()));
return result.take_error();
}
return zx::ok();
}
// Add a child device node and offer the service capabilities.
template <typename Protocol>
zx::result<> Driver::AddChild(std::string_view node_name, std::string_view class_name,
driver_devfs::Connector<Protocol>& devfs_connector) {
fidl::Arena arena;
zx::result connector = devfs_connector.Bind(dispatcher());
if (connector.is_error()) {
return connector.take_error();
}
auto devfs = fuchsia_driver_framework::wire::DevfsAddArgs::Builder(arena)
.connector(std::move(connector.value()))
.class_name(class_name);
auto args = fuchsia_driver_framework::wire::NodeAddArgs::Builder(arena)
.name(arena, node_name)
.devfs_args(devfs.Build())
.Build();
// Create endpoints of the `NodeController` for the node.
auto endpoints = fidl::CreateEndpoints<fuchsia_driver_framework::NodeController>();
if (endpoints.is_error()) {
FDF_SLOG(ERROR, "Failed to create endpoint", KV("status", endpoints.status_string()));
return zx::error(endpoints.status_value());
}
auto result = node_->AddChild(args, std::move(endpoints->server), {});
if (!result.ok()) {
FDF_SLOG(ERROR, "Failed to add child", KV("status", result.status_string()));
return zx::error(result.status());
}
controllers_.emplace_back(std::move(endpoints->client));
return zx::ok();
}
void Driver::ServeBattery(fidl::ServerEnd<fuchsia_hardware_powersource::Source> server) {
protocol_server_battery_.Serve(dispatcher(), std::move(server));
}
void Driver::ServeSimulatorBattery(
fidl::ServerEnd<fuchsia_hardware_powersource_test::SourceSimulator> server) {
simulator_server_battery_.Serve(dispatcher(), std::move(server));
}
void Driver::ServeAc(fidl::ServerEnd<fuchsia_hardware_powersource::Source> server) {
protocol_server_ac_.Serve(dispatcher(), std::move(server));
}
void Driver::ServeSimulatorAc(
fidl::ServerEnd<fuchsia_hardware_powersource_test::SourceSimulator> server) {
simulator_server_ac_.Serve(dispatcher(), std::move(server));
}
} // namespace fake_powersource
FUCHSIA_DRIVER_EXPORT(fake_powersource::Driver);