1 /** 2 * Copyright 2017 Google Inc. 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 17 #include "dbus_mode.hpp" 18 19 #include <ipmid/api.h> 20 21 #include <sdbusplus/bus.hpp> 22 #include <sdbusplus/message.hpp> 23 24 #include <cstdint> 25 #include <string> 26 #include <variant> 27 28 namespace pid_control 29 { 30 namespace ipmi 31 { 32 33 static constexpr auto objectPath = "/xyz/openbmc_project/settings/fanctrl/zone"; 34 static constexpr auto busName = "xyz.openbmc_project.State.FanCtrl"; 35 static constexpr auto intf = "xyz.openbmc_project.Control.Mode"; 36 static constexpr auto manualProperty = "Manual"; 37 static constexpr auto failsafeProperty = "FailSafe"; 38 static constexpr auto propertiesintf = "org.freedesktop.DBus.Properties"; 39 40 using Property = std::string; 41 using Value = std::variant<bool>; 42 using PropertyMap = std::map<Property, Value>; 43 44 /* The following was copied directly from my manual thread handler. */ 45 static std::string getControlPath(int8_t zone) 46 { 47 return std::string(objectPath) + std::to_string(zone); 48 } 49 50 uint8_t DbusZoneControl::getFanCtrlProperty(uint8_t zoneId, bool* value, 51 const std::string& property) 52 { 53 std::string path = getControlPath(zoneId); 54 55 auto propertyReadBus = sdbusplus::bus::new_system(); 56 auto pimMsg = propertyReadBus.new_method_call(busName, path.c_str(), 57 propertiesintf, "GetAll"); 58 pimMsg.append(intf); 59 60 try 61 { 62 PropertyMap propMap; 63 64 /* a method could error but the call not error. */ 65 auto valueResponseMsg = propertyReadBus.call(pimMsg); 66 67 valueResponseMsg.read(propMap); 68 69 *value = std::get<bool>(propMap[property]); 70 } 71 catch (const sdbusplus::exception::SdBusError& ex) 72 { 73 return IPMI_CC_INVALID; 74 } 75 76 return IPMI_CC_OK; 77 } 78 79 uint8_t DbusZoneControl::setFanCtrlProperty(uint8_t zoneId, bool value, 80 const std::string& property) 81 { 82 using Value = std::variant<bool>; 83 Value v{value}; 84 85 std::string path = getControlPath(zoneId); 86 87 auto PropertyWriteBus = sdbusplus::bus::new_system(); 88 auto pimMsg = PropertyWriteBus.new_method_call(busName, path.c_str(), 89 propertiesintf, "Set"); 90 pimMsg.append(intf); 91 pimMsg.append(property); 92 pimMsg.append(v); 93 94 try 95 { 96 PropertyWriteBus.call_noreply(pimMsg); 97 } 98 catch (const sdbusplus::exception::SdBusError& ex) 99 { 100 return IPMI_CC_INVALID; 101 } 102 103 /* TODO(venture): Should sanity check the result. */ 104 return IPMI_CC_OK; 105 } 106 107 } // namespace ipmi 108 } // namespace pid_control 109