| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 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 | */ | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 16 | #include "tach.hpp" | 
|  | 17 |  | 
|  | 18 | #include "rpolicy.hpp" | 
|  | 19 |  | 
| Brad Bishop | d37c0f8 | 2017-07-28 21:47:00 -0400 | [diff] [blame] | 20 | #include <phosphor-logging/log.hpp> | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 21 |  | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 22 | #include <string> | 
|  | 23 | #include <tuple> | 
|  | 24 | #include <vector> | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 25 |  | 
|  | 26 | namespace phosphor | 
|  | 27 | { | 
|  | 28 | namespace fan | 
|  | 29 | { | 
|  | 30 | namespace presence | 
|  | 31 | { | 
|  | 32 |  | 
| Brad Bishop | d37c0f8 | 2017-07-28 21:47:00 -0400 | [diff] [blame] | 33 | using namespace phosphor::logging; | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 34 | using namespace std::literals::string_literals; | 
|  | 35 |  | 
|  | 36 | static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s; | 
|  | 37 | static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s; | 
|  | 38 | static const auto tachProperty = "Value"s; | 
|  | 39 |  | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 40 | Tach::Tach(const std::vector<std::string>& sensors) : currentState(false) | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 41 | { | 
|  | 42 | // Initialize state. | 
|  | 43 | for (const auto& s : sensors) | 
|  | 44 | { | 
|  | 45 | state.emplace_back(s, nullptr, 0); | 
|  | 46 | } | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | bool Tach::start() | 
|  | 50 | { | 
|  | 51 | for (size_t i = 0; i < state.size(); ++i) | 
|  | 52 | { | 
|  | 53 | auto& s = state[i]; | 
|  | 54 | auto tachPath = tachNamespace + std::get<std::string>(s); | 
|  | 55 |  | 
|  | 56 | // Register for signal callbacks. | 
|  | 57 | std::get<1>(s) = std::make_unique<sdbusplus::bus::match::match>( | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 58 | util::SDBusPlus::getBus(), | 
|  | 59 | sdbusplus::bus::match::rules::propertiesChanged(tachPath, | 
|  | 60 | tachIface), | 
|  | 61 | [this, i](auto& msg) { this->propertiesChanged(i, msg); }); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 62 |  | 
|  | 63 | // Get an initial tach speed. | 
| Brad Bishop | d37c0f8 | 2017-07-28 21:47:00 -0400 | [diff] [blame] | 64 | try | 
|  | 65 | { | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 66 | std::get<double>(s) = util::SDBusPlus::getProperty<double>( | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 67 | tachPath, tachIface, tachProperty); | 
| Brad Bishop | d37c0f8 | 2017-07-28 21:47:00 -0400 | [diff] [blame] | 68 | } | 
|  | 69 | catch (std::exception&) | 
|  | 70 | { | 
|  | 71 | // Assume not spinning. | 
|  | 72 |  | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 73 | std::get<double>(s) = 0; | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 74 | log<level::INFO>("Unable to read fan tach sensor.", | 
|  | 75 | entry("SENSOR=%s", tachPath.c_str())); | 
| Brad Bishop | d37c0f8 | 2017-07-28 21:47:00 -0400 | [diff] [blame] | 76 | } | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 77 | } | 
|  | 78 |  | 
|  | 79 | // Set the initial state of the sensor. | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 80 | currentState = std::any_of(state.begin(), state.end(), [](const auto& s) { | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 81 | return std::get<double>(s) != 0; | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 82 | }); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 83 |  | 
|  | 84 | return currentState; | 
|  | 85 | } | 
|  | 86 |  | 
|  | 87 | void Tach::stop() | 
|  | 88 | { | 
|  | 89 | for (auto& s : state) | 
|  | 90 | { | 
|  | 91 | // De-register signal callbacks. | 
|  | 92 | std::get<1>(s) = nullptr; | 
|  | 93 | } | 
|  | 94 | } | 
|  | 95 |  | 
|  | 96 | bool Tach::present() | 
|  | 97 | { | 
|  | 98 | // Live query the tach readings. | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 99 | std::vector<double> values; | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 100 | for (const auto& s : state) | 
|  | 101 | { | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 102 | values.push_back(util::SDBusPlus::getProperty<double>( | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 103 | tachNamespace + std::get<std::string>(s), tachIface, tachProperty)); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 104 | } | 
|  | 105 |  | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 106 | return std::any_of(values.begin(), values.end(), | 
|  | 107 | [](const auto& v) { return v != 0; }); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 108 | } | 
|  | 109 |  | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 110 | void Tach::propertiesChanged(size_t sensor, sdbusplus::message::message& msg) | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 111 | { | 
|  | 112 | std::string iface; | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 113 | util::Properties<double> properties; | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 114 | msg.read(iface, properties); | 
|  | 115 |  | 
|  | 116 | propertiesChanged(sensor, properties); | 
|  | 117 | } | 
|  | 118 |  | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 119 | void Tach::propertiesChanged(size_t sensor, | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 120 | const util::Properties<double>& props) | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 121 | { | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 122 | // Find the Value property containing the speed. | 
|  | 123 | auto it = props.find(tachProperty); | 
|  | 124 | if (it != props.end()) | 
|  | 125 | { | 
| Matthew Barth | 9f93bd3 | 2020-05-28 16:57:14 -0500 | [diff] [blame] | 126 | auto& s = state[sensor]; | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 127 | std::get<double>(s) = std::get<double>(it->second); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 128 |  | 
| Matthew Barth | 2d2caa3 | 2020-05-26 11:07:24 -0500 | [diff] [blame] | 129 | auto newState = | 
| Matthew Barth | ad2cd24 | 2020-08-13 13:36:19 -0500 | [diff] [blame] | 130 | std::any_of(state.begin(), state.end(), | 
|  | 131 | [](const auto& s) { return std::get<double>(s) != 0; }); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 132 |  | 
|  | 133 | if (currentState != newState) | 
|  | 134 | { | 
| Brad Bishop | 11083ec | 2017-07-25 19:08:53 -0400 | [diff] [blame] | 135 | getPolicy().stateChanged(newState, *this); | 
| Brad Bishop | dd62e36 | 2017-06-14 16:54:03 -0400 | [diff] [blame] | 136 | currentState = newState; | 
|  | 137 | } | 
|  | 138 | } | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | } // namespace presence | 
|  | 142 | } // namespace fan | 
|  | 143 | } // namespace phosphor |