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