1// vim:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com>
4 *
5 * This file is licensed under the terms of the GNU Lesser General
6 * Public License 2.1.
7 * See the file COPYING-LGPL-2.1 for details.
8 */
9#pragma once
10
11#include <l4/sys/capability>
12#include <l4/sys/cxx/ipc_iface>
13#include <l4/sys/cxx/ipc_string>
14#include <l4/re/protocols.h>
15
16namespace L4Re {
17
18/**
19 * \brief Set of inhibitor locks, which inhibit specific actions when held.
20 *
21 * This interface provides access to a set of inhibitor locks, each determined
22 * by an ID that is specific to the Inhibitor object. Each individual lock
23 * shall prevent, a specific (implementation defined) action to be executed, as
24 * long as the lock is held.
25 *
26 * For example there can be an inhibitor lock to prevent a transition to
27 * suspend-to-RAM state and a different one to prevent shutdown.
28 *
29 * A client shall take an inhibitor lock if it needs to execute code
30 * before the action is taken. For example a lock-screen application shall grab
31 * an inhibitor lock for the suspend action to be able to lock the screen
32 * before the system goes to sleep.
33 *
34 * Inhibitor locks are usually closely related to specific events. Usually a
35 * server automatically subscribes a client holding a lock to the corresponding
36 * event. The server shall send the event to inform the client that an action
37 * is pending. Upon reception of the event, the client is supposed to release
38 * the corresponding inhibitor lock.
39 */
40class Inhibitor :
41  public L4::Kobject_t<Inhibitor, L4::Kobject, L4RE_PROTO_INHIBITOR>
42{
43public:
44  enum
45  {
46    Name_max = 20 ///< The maximum length of a lock's name.
47  };
48
49  /**
50   * \brief Acquire a specific inhibitor lock.
51   *
52   * \param id      ID of the inhibitor lock that the client intends to acquire
53   * \param reason  The reason why you need the lock. Used for informing the
54   *                user or debugging.
55   *
56   * \retval 0           Success
57   * \retval -L4_ENODEV  The specified `id` does not exist.
58   */
59  L4_INLINE_RPC(long, acquire, (l4_umword_t id, L4::Ipc::String<> reason));
60
61  /**
62   * \brief Release a specific inhibitor lock.
63   *
64   * \param id  The ID of the inhibitor lock to release.
65   *
66   * \retval 0           Success
67   * \retval -L4_ENODEV  Lock with the given `id` does not exist.
68   */
69  L4_INLINE_RPC(long, release, (l4_umword_t id));
70
71  /**
72   * \brief Get information for the next available inhibitor lock.
73   *
74   * \param name        A pointer to a buffer for the name of the lock.
75   * \param len         The length of the available buffer (usually #Name_max
76   *                    is used)
77   * \param current_id  The ID of the last available lock, use -1 to get the
78   *                    first lock.
79   * \param utcb        The UTCB to use for the message.
80   *
81   * \retval >0          The ID of the next available lock if there is one (in
82   *                     this case `name` shall contain the name of the
83   *                     inhibitor lock).
84   * \retval -L4_ENODEV  There are no more locks.
85   */
86  long next_lock_info(char *name, unsigned len, l4_mword_t current_id = -1,
87                      l4_utcb_t *utcb = l4_utcb())
88  {
89    L4::Ipc::String<char> name_buf(len , name);
90    long r = next_lock_info_t::call(c(), &current_id, name_buf, utcb);
91    if (r < 0)
92      return r;
93
94    return current_id;
95  }
96
97  L4_INLINE_RPC_NF(long, next_lock_info, (L4::Ipc::In_out<l4_mword_t *> current_id,
98                                          L4::Ipc::String<char> &name));
99
100  typedef L4::Typeid::Rpcs<acquire_t, release_t, next_lock_info_t> Rpcs;
101};
102
103}
104