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/log.hpp>
17 #include <phosphor-logging/elog.hpp>
18 #include <phosphor-logging/elog-errors.hpp>
19 #include <xyz/openbmc_project/Common/error.hpp>
20 #include <string>
21 #include "fan.hpp"
22 #include "utility.hpp"
23 #include "sdbusplus.hpp"
24 
25 namespace phosphor
26 {
27 namespace fan
28 {
29 namespace control
30 {
31 
32 // For throwing exception
33 using namespace phosphor::logging;
34 using InternalFailure = sdbusplus::xyz::openbmc_project::Common::
35                             Error::InternalFailure;
36 
37 constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
38 constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
39 constexpr auto FAN_TARGET_PROPERTY = "Target";
40 
41 
42 Fan::Fan(sdbusplus::bus::bus& bus, const FanDefinition& def):
43     _bus(bus),
44     _name(std::get<fanNamePos>(def)),
45     _interface(std::get<targetInterfacePos>(def))
46 {
47     std::string path;
48     auto sensors = std::get<sensorListPos>(def);
49     for (auto& s : sensors)
50     {
51         path = FAN_SENSOR_PATH + s;
52         _sensors.emplace_back(path);
53     }
54     // All sensors associated with this fan are set to same target speed,
55     // so only need to read target property from one.
56     if (!path.empty())
57     {
58         _targetSpeed = util::SDBusPlus::getProperty<uint64_t>(
59                 bus,
60                 path,
61                 _interface,
62                 FAN_TARGET_PROPERTY);
63     }
64 }
65 
66 
67 //TODO openbmc/openbmc#1524  Can cache this value when
68 //openbmc/openbmc#1496 is resolved.
69 std::string Fan::getService(const std::string& sensor)
70 {
71     return phosphor::fan::util::getService(sensor,
72                                            _interface,
73                                            _bus);
74 }
75 
76 
77 void Fan::setSpeed(uint64_t speed)
78 {
79     sdbusplus::message::variant<uint64_t> value = speed;
80     std::string property{FAN_TARGET_PROPERTY};
81 
82     for (auto& sensor : _sensors)
83     {
84         auto service = getService(sensor);
85 
86         auto method = _bus.new_method_call(service.c_str(),
87                                            sensor.c_str(),
88                                            PROPERTY_INTERFACE,
89                                            "Set");
90         method.append(_interface, property, value);
91 
92         auto response = _bus.call(method);
93         if (response.is_method_error())
94         {
95             log<level::ERR>(
96                 "Failed call to set fan speed ", entry("SENSOR=%s", sensor));
97             elog<InternalFailure>();
98         }
99     }
100 
101     _targetSpeed = speed;
102 }
103 
104 }
105 }
106 }
107