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