xref: /openbmc/phosphor-pid-control/sensors/builder.cpp (revision e1fa85942c66533699a3b785990d95e9c89b6050)
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 <iostream>
18 #include <map>
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 /* Configuration. */
24 #include "conf.hpp"
25 #include "dbus/dbushelper.hpp"
26 #include "dbus/dbuspassive.hpp"
27 #include "dbus/dbuswrite.hpp"
28 #include "dbuspassiveredundancy.hpp"
29 #include "errors/exception.hpp"
30 #include "interfaces.hpp"
31 #include "notimpl/readonly.hpp"
32 #include "notimpl/writeonly.hpp"
33 #include "sensors/build_utils.hpp"
34 #include "sensors/builder.hpp"
35 #include "sensors/host.hpp"
36 #include "sensors/manager.hpp"
37 #include "sensors/pluggable.hpp"
38 #include "sysfs/sysfsread.hpp"
39 #include "sysfs/sysfswrite.hpp"
40 
41 #include <sdbusplus/bus.hpp>
42 
43 namespace pid_control
44 {
45 
46 static constexpr bool deferSignals = true;
47 
buildSensors(const std::map<std::string,conf::SensorConfig> & config,sdbusplus::bus_t & passive,sdbusplus::bus_t & host)48 SensorManager buildSensors(
49     const std::map<std::string, conf::SensorConfig>& config,
50     sdbusplus::bus_t& passive, sdbusplus::bus_t& host)
51 {
52     SensorManager mgmr{passive, host};
53     auto& hostSensorBus = mgmr.getHostBus();
54     auto& passiveListeningBus = mgmr.getPassiveBus();
55 
56     for (const auto& it : config)
57     {
58         std::unique_ptr<ReadInterface> ri;
59         std::unique_ptr<WriteInterface> wi;
60 
61         std::string name = it.first;
62         const conf::SensorConfig* info = &it.second;
63 
64         std::cerr << "Sensor: " << name << " " << info->type << " ";
65         std::cerr << info->readPath << " " << info->writePath << "\n";
66 
67         IOInterfaceType rtype = getReadInterfaceType(info->readPath);
68         IOInterfaceType wtype = getWriteInterfaceType(info->writePath);
69 
70         // fan sensors can be ready any way and written others.
71         // fan sensors are the only sensors this is designed to write.
72         // Nothing here should be write-only, although, in theory a fan could
73         // be. I'm just not sure how that would fit together.
74         // TODO(venture): It should check with the ObjectMapper to check if
75         // that sensor exists on the Dbus.
76         switch (rtype)
77         {
78             case IOInterfaceType::DBUSPASSIVE:
79                 // we only need to make one match based on the dbus object
80                 static std::shared_ptr<DbusPassiveRedundancy> redundancy =
81                     std::make_shared<DbusPassiveRedundancy>(
82                         passiveListeningBus);
83 
84                 if (info->type == "fan")
85                 {
86                     ri = DbusPassive::createDbusPassive(
87                         passiveListeningBus, info->type, name,
88                         std::make_unique<DbusHelper>(passiveListeningBus), info,
89                         redundancy);
90                 }
91                 else
92                 {
93                     ri = DbusPassive::createDbusPassive(
94                         passiveListeningBus, info->type, name,
95                         std::make_unique<DbusHelper>(passiveListeningBus), info,
96                         nullptr);
97                 }
98                 if (ri == nullptr)
99                 {
100                     throw SensorBuildException(
101                         "Failed to create dbus passive sensor: " + name +
102                         " of type: " + info->type);
103                 }
104                 break;
105             case IOInterfaceType::EXTERNAL:
106                 // These are a special case for read-only.
107                 break;
108             case IOInterfaceType::SYSFS:
109                 ri = std::make_unique<SysFsRead>(info->readPath);
110                 break;
111             default:
112                 ri = std::make_unique<WriteOnly>();
113                 break;
114         }
115 
116         if (info->type == "fan")
117         {
118             switch (wtype)
119             {
120                 case IOInterfaceType::SYSFS:
121                     if (info->max > 0)
122                     {
123                         wi = std::make_unique<SysFsWritePercent>(
124                             info->writePath, info->min, info->max);
125                     }
126                     else
127                     {
128                         wi = std::make_unique<SysFsWrite>(info->writePath,
129                                                           info->min, info->max);
130                     }
131 
132                     break;
133                 case IOInterfaceType::DBUSACTIVE:
134                     if (info->max > 0)
135                     {
136                         wi = DbusWritePercent::createDbusWrite(
137                             info->writePath, info->min, info->max,
138                             std::make_unique<DbusHelper>(passiveListeningBus));
139                     }
140                     else
141                     {
142                         wi = DbusWrite::createDbusWrite(
143                             info->writePath, info->min, info->max,
144                             std::make_unique<DbusHelper>(passiveListeningBus));
145                     }
146 
147                     if (wi == nullptr)
148                     {
149                         throw SensorBuildException(
150                             "Unable to create write dbus interface for path: " +
151                             info->writePath);
152                     }
153 
154                     break;
155                 default:
156                     wi = std::make_unique<ReadOnlyNoExcept>();
157                     break;
158             }
159 
160             auto sensor = std::make_unique<PluggableSensor>(
161                 name, info->timeout, std::move(ri), std::move(wi),
162                 info->ignoreFailIfHostOff);
163             mgmr.addSensor(info->type, name, std::move(sensor));
164         }
165         else if (info->type == "temp" || info->type == "margin" ||
166                  info->type == "power" || info->type == "powersum")
167         {
168             // These sensors are read-only, but only for this application
169             // which only writes to fan sensors.
170             std::cerr << info->type << " readPath: " << info->readPath << "\n";
171 
172             if (IOInterfaceType::EXTERNAL == rtype)
173             {
174                 std::cerr << "Creating HostSensor: " << name
175                           << " path: " << info->readPath << "\n";
176 
177                 /*
178                  * The reason we handle this as a HostSensor is because it's
179                  * not quite pluggable; but maybe it could be.
180                  */
181                 auto sensor = HostSensor::createTemp(
182                     name, info->timeout, hostSensorBus, info->readPath.c_str(),
183                     deferSignals);
184                 mgmr.addSensor(info->type, name, std::move(sensor));
185             }
186             else
187             {
188                 wi = std::make_unique<ReadOnlyNoExcept>();
189                 auto sensor = std::make_unique<PluggableSensor>(
190                     name, info->timeout, std::move(ri), std::move(wi),
191                     info->ignoreFailIfHostOff);
192                 mgmr.addSensor(info->type, name, std::move(sensor));
193             }
194         }
195     }
196 
197     return mgmr;
198 }
199 
200 } // namespace pid_control
201