/** * Copyright © 2017 IBM Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "tach.hpp" #include "rpolicy.hpp" namespace phosphor { namespace fan { namespace presence { using namespace phosphor::logging; using namespace std::literals::string_literals; static const auto tachNamespace = "/xyz/openbmc_project/sensors/fan_tach/"s; static const auto tachIface = "xyz.openbmc_project.Sensor.Value"s; static const auto tachProperty = "Value"s; Tach::Tach( const std::vector& sensors) : currentState(false) { // Initialize state. for (const auto& s : sensors) { state.emplace_back(s, nullptr, 0); } } bool Tach::start() { for (size_t i = 0; i < state.size(); ++i) { auto& s = state[i]; auto tachPath = tachNamespace + std::get(s); // Register for signal callbacks. std::get<1>(s) = std::make_unique( util::SDBusPlus::getBus(), sdbusplus::bus::match::rules::propertiesChanged( tachPath, tachIface), [this, i](auto& msg){ this->propertiesChanged(i, msg);}); // Get an initial tach speed. try { std::get(s) = util::SDBusPlus::getProperty( tachPath, tachIface, tachProperty); } catch (std::exception&) { // Assume not spinning. std::get(s) = 0; log( "Unable to read fan tach sensor.", entry("SENSOR=%s", tachPath.c_str())); } } // Set the initial state of the sensor. currentState = std::any_of( state.begin(), state.end(), [](const auto & s) { return std::get(s) != 0; }); return currentState; } void Tach::stop() { for (auto& s : state) { // De-register signal callbacks. std::get<1>(s) = nullptr; } } bool Tach::present() { // Live query the tach readings. std::vector values; for (const auto& s : state) { values.push_back( util::SDBusPlus::getProperty( tachNamespace + std::get(s), tachIface, tachProperty)); } return std::any_of( values.begin(), values.end(), [](const auto & v) {return v != 0;}); } void Tach::propertiesChanged( size_t sensor, sdbusplus::message::message& msg) { std::string iface; util::Properties properties; msg.read(iface, properties); propertiesChanged(sensor, properties); } void Tach::propertiesChanged( size_t sensor, const util::Properties& props) { auto& s = state[sensor]; // Find the Value property containing the speed. auto it = props.find(tachProperty); if (it != props.end()) { std::get(s) = sdbusplus::message::variant_ns::get(it->second); auto newState = std::any_of( state.begin(), state.end(), [](const auto & s) { return std::get(s) != 0; }); if (currentState != newState) { getPolicy().stateChanged(newState, *this); currentState = newState; } } } } // namespace presence } // namespace fan } // namespace phosphor