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