/*
 * Copyright (C) 2017, 2019-2020, 2024 Kernkonzept GmbH.
 * Author: Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
 *         Adam Lackorzynski <adam@l4re.org>
 *
 * License: see LICENSE.spdx (in this directory or the directories above)
 */
#pragma once

#include "device.h"

#include <l4/vbus/vbus>
#include <l4/sys/platform_control>

namespace Vmm {

/**
 * Guest interface for system power control.
 *
 * Allows the guest to control machine suspend/shutdown. The underlying
 * technique is inhibitors that -if taken- prevent the system from
 * suspending/shutting down/rebooting. This interface acquires suspend and
 * shutdown inhibitors. It allows the guest to release them.
 *
 * If a L4::Platform control cap 'pfc' is available, this interface will
 * announce the guest's intent to this cap as well. This can be used to allow
 * a guest to suspend/shutdown/reboot the machine.
 */
class Pm
: public virtual Vdev::Dev_ref
{
public:
  Pm();
  virtual ~Pm();

  /**
   * Configure if guest should resume on system resume.
   *
   * If true, uvmm will acquire a wakeup inhibitor prior to releasing its
   * suspend inhibitor. IO sends a wakeup event to all clients holding a
   * wakeup inhibitor on system resume. This can be used to resume the guest
   * on system resume.
   */
  void use_wakeup_inhibitor(bool val)
  {
    _use_wakeup_inhibitor = val;
  }

  bool suspend();
  void resume();
  void shutdown(bool reboot = false);
  void free_inhibitors();

private:
  L4::Cap<L4Re::Inhibitor> _vbus;
  L4::Cap<L4::Platform_control> _pfc;

  bool _use_wakeup_inhibitor = false;

  /**
   * \pre _vbus must be valid
   */
  bool acquire_wakeup_inhibitor();
};

} // namespace
