blob: 8d6580ecb5defa607cc8da80c22fd9ce392664ba [file] [log] [blame] [edit]
// Copyright 2024 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.
#ifndef SRC_DEVICES_SUSPEND_DRIVERS_GENERIC_SUSPEND_GENERIC_SUSPEND_H_
#define SRC_DEVICES_SUSPEND_DRIVERS_GENERIC_SUSPEND_GENERIC_SUSPEND_H_
#include <fidl/fuchsia.hardware.power.suspend/cpp/fidl.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/driver/devfs/cpp/connector.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/inspect/cpp/inspect.h>
#include <zircon/syscalls-next.h>
#include "lib/fdf/cpp/dispatcher.h"
namespace suspend {
/// Maximum supported wake source report entries.
constexpr uint32_t kMaxWakeSourceEntriesCount = 100;
/// Reports the information about wake sources as reported by the kernel upon
/// call to `zx_system_suspend_enter`.
struct WakeSourceReport {
/// The kernel's wake source report header information, always filled out.
zx_wake_source_report_header_t header;
/// The number of wake sources available in the kernel to report. This number
/// may be larger than `kMaxWakeSourceEntriesCount`, in which case the overflow
/// is simply omitted.
uint32_t actual_entry_count;
/// The wake source details as reported by the kernel. We forward a maximum
/// of `kMaxWakeSourceEntriesCount`, if there are more those are not reported.
///
/// However, the specified maximum number of entries should be enough for
/// everyone.
zx_wake_source_report_entry_t entries[kMaxWakeSourceEntriesCount];
};
class GenericSuspend : public fdf::DriverBase,
public fidl::WireServer<fuchsia_hardware_power_suspend::Suspender> {
public:
GenericSuspend(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher dispatcher);
zx::result<> Start() override;
void PrepareStop(fdf::PrepareStopCompleter completer) override;
void Stop() override;
void handle_unknown_method(
fidl::UnknownMethodMetadata<fuchsia_hardware_power_suspend::Suspender> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override {
FDF_LOG(ERROR, "Unexpected suspend FIDL call: 0x%lx", metadata.method_ordinal);
}
void GetSuspendStates(GetSuspendStatesCompleter::Sync& completer) override;
void Suspend(SuspendRequestView request, SuspendCompleter::Sync& completer) override;
void ForceLowestPowerMode(ForceLowestPowerModeRequestView request,
ForceLowestPowerModeCompleter::Sync& completer) override;
protected:
virtual zx::result<zx::resource> GetCpuResource();
virtual zx::result<WakeSourceReport> SystemSuspendEnter();
// Called just at Start(). Used in testing, otherwise a no-op.
virtual void AtStart() {}
private:
void Serve(fidl::ServerEnd<fuchsia_hardware_power_suspend::Suspender> request);
zx::result<> CreateDevfsNode();
inspect::BoundedListNode inspect_events_;
fidl::ServerBindingGroup<fuchsia_hardware_power_suspend::Suspender> suspend_bindings_;
fidl::WireSyncClient<fuchsia_driver_framework::Node> parent_;
fidl::WireSyncClient<fuchsia_driver_framework::NodeController> controller_;
driver_devfs::Connector<fuchsia_hardware_power_suspend::Suspender> devfs_connector_;
zx::resource cpu_resource_;
};
} // namespace suspend
#endif // SRC_DEVICES_SUSPEND_DRIVERS_GENERIC_SUSPEND_GENERIC_SUSPEND_H_