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