1 /**
2  * Copyright © 2020 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "action.hpp"
19 #include "services.hpp"
20 
21 #include <memory>
22 #include <optional>
23 #include <utility>
24 #include <vector>
25 
26 namespace phosphor::power::regulators
27 {
28 
29 // Forward declarations to avoid circular dependencies
30 class Chassis;
31 class Device;
32 class System;
33 
34 /**
35  * @class PresenceDetection
36  *
37  * Specifies how to detect whether a device is present.
38  *
39  * Some devices are only present in certain system configurations.  For example:
40  * - A regulator is only present when a related processor or memory module is
41  *   present.
42  * - A system supports multiple storage backplane types, and the device only
43  *   exists on one of the backplanes.
44  *
45  * Device presence is detected by executing actions, such as
46  * ComparePresenceAction and CompareVPDAction.
47  *
48  * Device operations like configuration and sensor monitoring will only be
49  * performed if the actions indicate the device is present.
50  *
51  * Device presence will only be detected once per boot of the system.  Presence
52  * will be determined prior to the first device operation (such as
53  * configuration).  When the system is re-booted, presence will be re-detected.
54  * As a result, presence detection is not supported for devices that can be
55  * removed or added (hot-plugged) while the system is booted and running.
56  */
57 class PresenceDetection
58 {
59   public:
60     // Specify which compiler-generated methods we want
61     PresenceDetection() = delete;
62     PresenceDetection(const PresenceDetection&) = delete;
63     PresenceDetection(PresenceDetection&&) = delete;
64     PresenceDetection& operator=(const PresenceDetection&) = delete;
65     PresenceDetection& operator=(PresenceDetection&&) = delete;
66     ~PresenceDetection() = default;
67 
68     /**
69      * Constructor.
70      *
71      * @param actions actions that detect whether the device is present
72      */
73     explicit PresenceDetection(std::vector<std::unique_ptr<Action>> actions) :
74         actions{std::move(actions)}
75     {
76     }
77 
78     /**
79      * Clears the cached presence value.
80      */
81     void clearCache(void)
82     {
83         isPresent.reset();
84     }
85 
86     /**
87      * Executes the actions to detect whether the device is present.
88      *
89      * The return value of the last action indicates whether the device is
90      * present.  A return value of true means the device is present; false means
91      * the device is missing.
92      *
93      * Caches the resulting presence value.  Subsequent calls to execute() will
94      * return the cached value rather than re-executing the actions.  This
95      * provides a performance improvement since the actions may be expensive to
96      * execute, such as I2C reads or D-Bus method calls.  The cached value can
97      * be cleared by calling clearCache().
98      *
99      * @return true if device is present, false otherwise
100      */
101     bool execute(Services& services, System& system, Chassis& chassis,
102                  Device& device);
103 
104     /**
105      * Returns the actions that detect whether the device is present.
106      *
107      * @return actions
108      */
109     const std::vector<std::unique_ptr<Action>>& getActions() const
110     {
111         return actions;
112     }
113 
114     /**
115      * Returns the cached presence value, if any.
116      *
117      * @return cached presence value
118      */
119     std::optional<bool> getCachedPresence() const
120     {
121         return isPresent;
122     }
123 
124   private:
125     /**
126      * Actions that detect whether the device is present.
127      */
128     std::vector<std::unique_ptr<Action>> actions{};
129 
130     /**
131      * Cached presence value.  Initially has no value.
132      */
133     std::optional<bool> isPresent{};
134 };
135 
136 } // namespace phosphor::power::regulators
137