xref: /openbmc/phosphor-fan-presence/presence/fallback.cpp (revision 8dab554bdea48ba57ec056c2352a58e55260af5a)
1  /**
2   * Copyright © 2017 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  #include "fallback.hpp"
17  
18  #include "fan.hpp"
19  #include "psensor.hpp"
20  
21  #include <phosphor-logging/log.hpp>
22  
23  #include <algorithm>
24  #include <format>
25  
26  namespace phosphor
27  {
28  namespace fan
29  {
30  namespace presence
31  {
32  
33  void Fallback::stateChanged(bool present, PresenceSensor& /*sensor*/)
34  {
35      if (!present)
36      {
37          // Starting with the first backup, find the first
38          // sensor that reports the fan as present, if any.
39          auto it = std::find_if(std::next(activeSensor), sensors.end(),
40                                 [](auto& s) { return s.get().present(); });
41  
42          if (it != sensors.end())
43          {
44              // A backup sensor disagrees with the active sensor.
45              // Switch to the backup.
46              activeSensor->get().stop();
47              present = it->get().start();
48  
49              while (activeSensor != it)
50              {
51                  // Callout the broken sensors.
52                  activeSensor->get().fail();
53                  ++activeSensor;
54              }
55              phosphor::logging::log<phosphor::logging::level::INFO>(
56                  std::format("Using backup presence sensor for fan {}",
57                              std::get<1>(fan))
58                      .c_str());
59              activeSensor = it;
60          }
61      }
62  
63      setPresence(fan, present);
64  
65      if (eepromDevice)
66      {
67          if (present)
68          {
69              eepromDevice->bind();
70          }
71          else
72          {
73              eepromDevice->unbind();
74          }
75      }
76  }
77  
78  void Fallback::monitor()
79  {
80      // Find the first sensor that says the fan is present
81      // and set it as the active sensor.
82      activeSensor = std::find_if(sensors.begin(), sensors.end(), [](auto& s) {
83          return s.get().present();
84      });
85      if (activeSensor == sensors.end())
86      {
87          // The first sensor is working or all sensors
88          // agree the fan isn't present.  Use the first sensor.
89          activeSensor = sensors.begin();
90      }
91  
92      if (activeSensor != sensors.begin())
93      {
94          phosphor::logging::log<phosphor::logging::level::INFO>(
95              std::format("Using backup presence sensor for fan {}",
96                          std::get<1>(fan))
97                  .c_str());
98      }
99  
100      // Callout the broken sensors.
101      auto it = sensors.begin();
102      while (it != activeSensor)
103      {
104          it->get().fail();
105          ++it;
106      }
107  
108      // Start the active sensor and set the initial state.
109      setPresence(fan, activeSensor->get().start());
110  }
111  
112  } // namespace presence
113  } // namespace fan
114  } // namespace phosphor
115