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      * Clears the cached presence value.
79      */
80     void clearCache(void)
81     {
82         isPresent.reset();
83     }
84 
85     /**
86      * Executes the actions to detect whether the device is present.
87      *
88      * The return value of the last action indicates whether the device is
89      * present.  A return value of true means the device is present; false means
90      * the device is missing.
91      *
92      * Caches the resulting presence value.  Subsequent calls to execute() will
93      * return the cached value rather than re-executing the actions.  This
94      * provides a performance improvement since the actions may be expensive to
95      * execute, such as I2C reads or D-Bus method calls.  The cached value can
96      * be cleared by calling clearCache().
97      *
98      * @return true if device is present, false otherwise
99      */
100     bool execute(Services& services, System& system, Chassis& chassis,
101                  Device& device);
102 
103     /**
104      * Returns the actions that detect whether the device is present.
105      *
106      * @return actions
107      */
108     const std::vector<std::unique_ptr<Action>>& getActions() const
109     {
110         return actions;
111     }
112 
113     /**
114      * Returns the cached presence value, if any.
115      *
116      * @return cached presence value
117      */
118     std::optional<bool> getCachedPresence() const
119     {
120         return isPresent;
121     }
122 
123   private:
124     /**
125      * Actions that detect whether the device is present.
126      */
127     std::vector<std::unique_ptr<Action>> actions{};
128 
129     /**
130      * Cached presence value.  Initially has no value.
131      */
132     std::optional<bool> isPresent{};
133 };
134 
135 } // namespace phosphor::power::regulators
136