17f88fe61SMatt Spinler /** 27f88fe61SMatt Spinler * Copyright © 2017 IBM Corporation 37f88fe61SMatt Spinler * 47f88fe61SMatt Spinler * Licensed under the Apache License, Version 2.0 (the "License"); 57f88fe61SMatt Spinler * you may not use this file except in compliance with the License. 67f88fe61SMatt Spinler * You may obtain a copy of the License at 77f88fe61SMatt Spinler * 87f88fe61SMatt Spinler * http://www.apache.org/licenses/LICENSE-2.0 97f88fe61SMatt Spinler * 107f88fe61SMatt Spinler * Unless required by applicable law or agreed to in writing, software 117f88fe61SMatt Spinler * distributed under the License is distributed on an "AS IS" BASIS, 127f88fe61SMatt Spinler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137f88fe61SMatt Spinler * See the License for the specific language governing permissions and 147f88fe61SMatt Spinler * limitations under the License. 157f88fe61SMatt Spinler */ 16*df3e8d67SMatthew Barth #include <phosphor-logging/elog.hpp> 177f88fe61SMatt Spinler #include "zone.hpp" 18*df3e8d67SMatthew Barth #include "utility.hpp" 197f88fe61SMatt Spinler 207f88fe61SMatt Spinler namespace phosphor 217f88fe61SMatt Spinler { 227f88fe61SMatt Spinler namespace fan 237f88fe61SMatt Spinler { 247f88fe61SMatt Spinler namespace control 257f88fe61SMatt Spinler { 267f88fe61SMatt Spinler 27*df3e8d67SMatthew Barth using namespace phosphor::logging; 287f88fe61SMatt Spinler 2914184131SMatthew Barth Zone::Zone(Mode mode, 3014184131SMatthew Barth sdbusplus::bus::bus& bus, 317f88fe61SMatt Spinler const ZoneDefinition& def) : 327f88fe61SMatt Spinler _bus(bus), 337f88fe61SMatt Spinler _fullSpeed(std::get<fullSpeedPos>(def)), 347f88fe61SMatt Spinler _zoneNum(std::get<zoneNumPos>(def)) 357f88fe61SMatt Spinler { 367f88fe61SMatt Spinler auto& fanDefs = std::get<fanListPos>(def); 377f88fe61SMatt Spinler 387f88fe61SMatt Spinler for (auto& def : fanDefs) 397f88fe61SMatt Spinler { 407f88fe61SMatt Spinler _fans.emplace_back(std::make_unique<Fan>(bus, def)); 417f88fe61SMatt Spinler } 4238a93a8aSMatthew Barth 4314184131SMatthew Barth // Do not enable set speed events when in init mode 4414184131SMatthew Barth if (mode != Mode::init) 4514184131SMatthew Barth { 4617d1fe23SMatthew Barth // Setup signal trigger for set speed events 4738a93a8aSMatthew Barth for (auto& event : std::get<setSpeedEventsPos>(def)) 4838a93a8aSMatthew Barth { 49*df3e8d67SMatthew Barth // Get the current value for each property 50*df3e8d67SMatthew Barth for (auto& entry : std::get<groupPos>(event)) 51*df3e8d67SMatthew Barth { 52*df3e8d67SMatthew Barth try 53*df3e8d67SMatthew Barth { 54*df3e8d67SMatthew Barth bool value = false; 55*df3e8d67SMatthew Barth getProperty(_bus, 56*df3e8d67SMatthew Barth entry.first, 57*df3e8d67SMatthew Barth std::get<intfPos>(entry.second), 58*df3e8d67SMatthew Barth std::get<propPos>(entry.second), 59*df3e8d67SMatthew Barth value); 60*df3e8d67SMatthew Barth setPropertyValue(entry.first.c_str(), 61*df3e8d67SMatthew Barth std::get<propPos>(entry.second).c_str(), 62*df3e8d67SMatthew Barth value); 63*df3e8d67SMatthew Barth } 64*df3e8d67SMatthew Barth catch (const std::exception& e) 65*df3e8d67SMatthew Barth { 66*df3e8d67SMatthew Barth log<level::ERR>(e.what()); 67*df3e8d67SMatthew Barth } 68*df3e8d67SMatthew Barth } 69*df3e8d67SMatthew Barth // Setup signal matches for property change events 7017d1fe23SMatthew Barth for (auto& prop : std::get<propChangeListPos>(event)) 7138a93a8aSMatthew Barth { 7238a93a8aSMatthew Barth _signalEvents.emplace_back( 7314184131SMatthew Barth std::make_unique<SignalEvent>( 7414184131SMatthew Barth this, 7517d1fe23SMatthew Barth EventData 7617d1fe23SMatthew Barth { 7717d1fe23SMatthew Barth std::get<groupPos>(event), 7817d1fe23SMatthew Barth std::get<handlerObjPos>(prop), 7917d1fe23SMatthew Barth std::get<actionPos>(event) 8017d1fe23SMatthew Barth })); 8114184131SMatthew Barth _matches.emplace_back( 8214184131SMatthew Barth bus, 8338a93a8aSMatthew Barth std::get<signaturePos>(prop).c_str(), 8438a93a8aSMatthew Barth signalHandler, 8538a93a8aSMatthew Barth _signalEvents.back().get()); 8638a93a8aSMatthew Barth } 87*df3e8d67SMatthew Barth // Run action function for initial event state 88*df3e8d67SMatthew Barth std::get<actionPos>(event)(*this, 89*df3e8d67SMatthew Barth std::get<groupPos>(event)); 9038a93a8aSMatthew Barth } 917f88fe61SMatt Spinler } 9214184131SMatthew Barth } 937f88fe61SMatt Spinler 947f88fe61SMatt Spinler 957f88fe61SMatt Spinler void Zone::setSpeed(uint64_t speed) 967f88fe61SMatt Spinler { 977f88fe61SMatt Spinler for (auto& fan : _fans) 987f88fe61SMatt Spinler { 997f88fe61SMatt Spinler fan->setSpeed(speed); 1007f88fe61SMatt Spinler } 1017f88fe61SMatt Spinler } 1027f88fe61SMatt Spinler 103861d77c3SMatthew Barth void Zone::setActiveAllow(const Group* group, bool isActiveAllow) 104861d77c3SMatthew Barth { 105861d77c3SMatthew Barth _active[group] = isActiveAllow; 106861d77c3SMatthew Barth if (!isActiveAllow) 107861d77c3SMatthew Barth { 108861d77c3SMatthew Barth _isActive = false; 109861d77c3SMatthew Barth } 110861d77c3SMatthew Barth else 111861d77c3SMatthew Barth { 112861d77c3SMatthew Barth // Check all entries are set to allow control active 113861d77c3SMatthew Barth auto actPred = [](auto const& entry) {return entry.second;}; 114861d77c3SMatthew Barth _isActive = std::all_of(_active.begin(), 115861d77c3SMatthew Barth _active.end(), 116861d77c3SMatthew Barth actPred); 117861d77c3SMatthew Barth } 118861d77c3SMatthew Barth } 119861d77c3SMatthew Barth 120*df3e8d67SMatthew Barth template <typename T> 121*df3e8d67SMatthew Barth void Zone::getProperty(sdbusplus::bus::bus& bus, 122*df3e8d67SMatthew Barth const std::string& path, 123*df3e8d67SMatthew Barth const std::string& iface, 124*df3e8d67SMatthew Barth const std::string& prop, 125*df3e8d67SMatthew Barth T& value) 126*df3e8d67SMatthew Barth { 127*df3e8d67SMatthew Barth sdbusplus::message::variant<T> property; 128*df3e8d67SMatthew Barth auto serv = phosphor::fan::util::getService(path, iface, bus); 129*df3e8d67SMatthew Barth auto hostCall = bus.new_method_call(serv.c_str(), 130*df3e8d67SMatthew Barth path.c_str(), 131*df3e8d67SMatthew Barth "org.freedesktop.DBus.Properties", 132*df3e8d67SMatthew Barth "Get"); 133*df3e8d67SMatthew Barth hostCall.append(iface); 134*df3e8d67SMatthew Barth hostCall.append(prop); 135*df3e8d67SMatthew Barth auto hostResponseMsg = bus.call(hostCall); 136*df3e8d67SMatthew Barth if (hostResponseMsg.is_method_error()) 137*df3e8d67SMatthew Barth { 138*df3e8d67SMatthew Barth throw std::runtime_error( 139*df3e8d67SMatthew Barth "Error in host call response for retrieving property"); 140*df3e8d67SMatthew Barth } 141*df3e8d67SMatthew Barth hostResponseMsg.read(property); 142*df3e8d67SMatthew Barth value = sdbusplus::message::variant_ns::get<T>(property); 143*df3e8d67SMatthew Barth } 144*df3e8d67SMatthew Barth 14538a93a8aSMatthew Barth int Zone::signalHandler(sd_bus_message* msg, 14638a93a8aSMatthew Barth void* data, 14738a93a8aSMatthew Barth sd_bus_error* err) 14838a93a8aSMatthew Barth { 14938a93a8aSMatthew Barth auto sdbpMsg = sdbusplus::message::message(msg); 15038a93a8aSMatthew Barth auto& signalEvent = *static_cast<SignalEvent*>(data); 15138a93a8aSMatthew Barth std::get<zoneObjPos>(signalEvent)->handleEvent( 15238a93a8aSMatthew Barth sdbpMsg, 15317d1fe23SMatthew Barth std::get<eventDataPos>(signalEvent)); 15438a93a8aSMatthew Barth return 0; 15538a93a8aSMatthew Barth } 15638a93a8aSMatthew Barth 15738a93a8aSMatthew Barth void Zone::handleEvent(sdbusplus::message::message& msg, 15817d1fe23SMatthew Barth const EventData& eventData) 15938a93a8aSMatthew Barth { 16038a93a8aSMatthew Barth // Handle the callback 16117d1fe23SMatthew Barth std::get<eventHandlerPos>(eventData)(_bus, msg, *this); 16217d1fe23SMatthew Barth // Perform the action 16317d1fe23SMatthew Barth std::get<eventActionPos>(eventData)(*this, 16417d1fe23SMatthew Barth std::get<eventGroupPos>(eventData)); 16538a93a8aSMatthew Barth } 16638a93a8aSMatthew Barth 1677f88fe61SMatt Spinler } 1687f88fe61SMatt Spinler } 1697f88fe61SMatt Spinler } 170