blob: a784f94d0d545a405bcd21e17e215c733c1a0d33 [file] [log] [blame]
Brad Bishopdd62e362017-06-14 16:54:03 -04001/**
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 */
Brad Bishopd37c0f82017-07-28 21:47:00 -040016#include <phosphor-logging/log.hpp>
Brad Bishopdd62e362017-06-14 16:54:03 -040017#include <string>
18#include <tuple>
19#include <vector>
20#include "tach.hpp"
21#include "rpolicy.hpp"
22
23namespace phosphor
24{
25namespace fan
26{
27namespace presence
28{
29
Brad Bishopd37c0f82017-07-28 21:47:00 -040030using namespace phosphor::logging;
Brad Bishopdd62e362017-06-14 16:54:03 -040031using namespace std::literals::string_literals;
32
33static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s;
34static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s;
35static const auto tachProperty = "Value"s;
36
37Tach::Tach(
38 const std::vector<std::string>& sensors) : currentState(false)
39{
40 // Initialize state.
41 for (const auto& s : sensors)
42 {
43 state.emplace_back(s, nullptr, 0);
44 }
45}
46
47bool Tach::start()
48{
49 for (size_t i = 0; i < state.size(); ++i)
50 {
51 auto& s = state[i];
52 auto tachPath = tachNamespace + std::get<std::string>(s);
53
54 // Register for signal callbacks.
55 std::get<1>(s) = std::make_unique<sdbusplus::bus::match::match>(
56 util::SDBusPlus::getBus(),
57 sdbusplus::bus::match::rules::propertiesChanged(
58 tachPath, tachIface),
59 [this, i](auto& msg){ this->propertiesChanged(i, msg);});
60
61 // Get an initial tach speed.
Brad Bishopd37c0f82017-07-28 21:47:00 -040062 try
63 {
64 std::get<int64_t>(s) = util::SDBusPlus::getProperty<int64_t>(
65 tachPath,
66 tachIface,
67 tachProperty);
68 }
69 catch (std::exception&)
70 {
71 // Assume not spinning.
72
73 std::get<int64_t>(s) = 0;
74 log<level::INFO>(
75 "Unable to read fan tach sensor.",
Matt Spinler84f105b2018-04-25 15:20:38 -050076 entry("SENSOR=%s", tachPath.c_str()));
Brad Bishopd37c0f82017-07-28 21:47:00 -040077
78 }
Brad Bishopdd62e362017-06-14 16:54:03 -040079 }
80
81 // Set the initial state of the sensor.
82 currentState = std::any_of(
83 state.begin(),
84 state.end(),
85 [](const auto & s)
86 {
87 return std::get<int64_t>(s) != 0;
88 });
89
90 return currentState;
91}
92
93void Tach::stop()
94{
95 for (auto& s : state)
96 {
97 // De-register signal callbacks.
98 std::get<1>(s) = nullptr;
99 }
100}
101
102bool Tach::present()
103{
104 // Live query the tach readings.
105 std::vector<int64_t> values;
106 for (const auto& s : state)
107 {
108 values.push_back(
109 util::SDBusPlus::getProperty<int64_t>(
110 tachNamespace + std::get<std::string>(s),
111 tachIface,
112 tachProperty));
113 }
114
115 return std::any_of(
116 values.begin(),
117 values.end(),
118 [](const auto & v) {return v != 0;});
119}
120
121void Tach::propertiesChanged(
122 size_t sensor,
123 sdbusplus::message::message& msg)
124{
125 std::string iface;
126 util::Properties<int64_t> properties;
127 msg.read(iface, properties);
128
129 propertiesChanged(sensor, properties);
130}
131
132void Tach::propertiesChanged(
133 size_t sensor,
134 const util::Properties<int64_t>& props)
135{
136 auto& s = state[sensor];
137
138 // Find the Value property containing the speed.
139 auto it = props.find(tachProperty);
140 if (it != props.end())
141 {
142 std::get<int64_t>(s) =
143 sdbusplus::message::variant_ns::get<int64_t>(it->second);
144
145 auto newState = std::any_of(
146 state.begin(),
147 state.end(),
148 [](const auto & s)
149 {
150 return std::get<int64_t>(s) != 0;
151 });
152
153 if (currentState != newState)
154 {
Brad Bishop11083ec2017-07-25 19:08:53 -0400155 getPolicy().stateChanged(newState, *this);
Brad Bishopdd62e362017-06-14 16:54:03 -0400156 currentState = newState;
157 }
158 }
159}
160
161} // namespace presence
162} // namespace fan
163} // namespace phosphor