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 <phosphor-logging/elog.hpp> 17 #include "zone.hpp" 18 #include "utility.hpp" 19 20 namespace phosphor 21 { 22 namespace fan 23 { 24 namespace control 25 { 26 27 using namespace phosphor::logging; 28 29 Zone::Zone(Mode mode, 30 sdbusplus::bus::bus& bus, 31 const ZoneDefinition& def) : 32 _bus(bus), 33 _fullSpeed(std::get<fullSpeedPos>(def)), 34 _zoneNum(std::get<zoneNumPos>(def)) 35 { 36 auto& fanDefs = std::get<fanListPos>(def); 37 38 for (auto& def : fanDefs) 39 { 40 _fans.emplace_back(std::make_unique<Fan>(bus, def)); 41 } 42 43 // Do not enable set speed events when in init mode 44 if (mode != Mode::init) 45 { 46 // Setup signal trigger for set speed events 47 for (auto& event : std::get<setSpeedEventsPos>(def)) 48 { 49 // Get the current value for each property 50 for (auto& entry : std::get<groupPos>(event)) 51 { 52 try 53 { 54 bool value = false; 55 getProperty(_bus, 56 entry.first, 57 std::get<intfPos>(entry.second), 58 std::get<propPos>(entry.second), 59 value); 60 setPropertyValue(entry.first.c_str(), 61 std::get<propPos>(entry.second).c_str(), 62 value); 63 } 64 catch (const std::exception& e) 65 { 66 log<level::ERR>(e.what()); 67 } 68 } 69 // Setup signal matches for property change events 70 for (auto& prop : std::get<propChangeListPos>(event)) 71 { 72 _signalEvents.emplace_back( 73 std::make_unique<EventData>( 74 EventData 75 { 76 std::get<groupPos>(event), 77 std::get<handlerObjPos>(prop), 78 std::get<actionPos>(event) 79 })); 80 _matches.emplace_back( 81 bus, 82 std::get<signaturePos>(prop).c_str(), 83 std::bind(std::mem_fn(&Zone::handleEvent), 84 this, 85 std::placeholders::_1, 86 _signalEvents.back().get())); 87 } 88 // Run action function for initial event state 89 std::get<actionPos>(event)(*this, 90 std::get<groupPos>(event)); 91 } 92 } 93 } 94 95 96 void Zone::setSpeed(uint64_t speed) 97 { 98 for (auto& fan : _fans) 99 { 100 fan->setSpeed(speed); 101 } 102 } 103 104 void Zone::setActiveAllow(const Group* group, bool isActiveAllow) 105 { 106 _active[group] = isActiveAllow; 107 if (!isActiveAllow) 108 { 109 _isActive = false; 110 } 111 else 112 { 113 // Check all entries are set to allow control active 114 auto actPred = [](auto const& entry) {return entry.second;}; 115 _isActive = std::all_of(_active.begin(), 116 _active.end(), 117 actPred); 118 } 119 } 120 121 template <typename T> 122 void Zone::getProperty(sdbusplus::bus::bus& bus, 123 const std::string& path, 124 const std::string& iface, 125 const std::string& prop, 126 T& value) 127 { 128 sdbusplus::message::variant<T> property; 129 auto serv = phosphor::fan::util::getService(path, iface, bus); 130 auto hostCall = bus.new_method_call(serv.c_str(), 131 path.c_str(), 132 "org.freedesktop.DBus.Properties", 133 "Get"); 134 hostCall.append(iface); 135 hostCall.append(prop); 136 auto hostResponseMsg = bus.call(hostCall); 137 if (hostResponseMsg.is_method_error()) 138 { 139 throw std::runtime_error( 140 "Error in host call response for retrieving property"); 141 } 142 hostResponseMsg.read(property); 143 value = sdbusplus::message::variant_ns::get<T>(property); 144 } 145 146 void Zone::handleEvent(sdbusplus::message::message& msg, 147 const EventData* eventData) 148 { 149 // Handle the callback 150 std::get<eventHandlerPos>(*eventData)(_bus, msg, *this); 151 // Perform the action 152 std::get<eventActionPos>(*eventData)(*this, 153 std::get<eventGroupPos>(*eventData)); 154 } 155 156 } 157 } 158 } 159