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 // we only need to make one match based on the dbus object 72 static std::shared_ptr<DbusPassiveRedundancy> redundancy = 73 std::make_shared<DbusPassiveRedundancy>( 74 passiveListeningBus); 75 76 if (info->type == "fan") 77 { 78 ri = DbusPassive::createDbusPassive( 79 passiveListeningBus, info->type, name, &helper, info, 80 redundancy); 81 } 82 else 83 { 84 ri = DbusPassive::createDbusPassive(passiveListeningBus, 85 info->type, name, 86 &helper, info, nullptr); 87 } 88 if (ri == nullptr) 89 { 90 throw SensorBuildException( 91 "Failed to create dbus passive sensor: " + name + 92 " of type: " + info->type); 93 } 94 break; 95 case IOInterfaceType::EXTERNAL: 96 // These are a special case for read-only. 97 break; 98 case IOInterfaceType::SYSFS: 99 ri = std::make_unique<SysFsRead>(info->readPath); 100 break; 101 default: 102 ri = std::make_unique<WriteOnly>(); 103 break; 104 } 105 106 if (info->type == "fan") 107 { 108 switch (wtype) 109 { 110 case IOInterfaceType::SYSFS: 111 if (info->max > 0) 112 { 113 wi = std::make_unique<SysFsWritePercent>( 114 info->writePath, info->min, info->max); 115 } 116 else 117 { 118 wi = std::make_unique<SysFsWrite>(info->writePath, 119 info->min, info->max); 120 } 121 122 break; 123 case IOInterfaceType::DBUSACTIVE: 124 if (info->max > 0) 125 { 126 wi = DbusWritePercent::createDbusWrite( 127 info->writePath, info->min, info->max, helper); 128 } 129 else 130 { 131 wi = DbusWrite::createDbusWrite( 132 info->writePath, info->min, info->max, helper); 133 } 134 135 if (wi == nullptr) 136 { 137 throw SensorBuildException( 138 "Unable to create write dbus interface for path: " + 139 info->writePath); 140 } 141 142 break; 143 default: 144 wi = std::make_unique<ReadOnlyNoExcept>(); 145 break; 146 } 147 148 auto sensor = std::make_unique<PluggableSensor>( 149 name, info->timeout, std::move(ri), std::move(wi)); 150 mgmr.addSensor(info->type, name, std::move(sensor)); 151 } 152 else if (info->type == "temp" || info->type == "margin") 153 { 154 // These sensors are read-only, but only for this application 155 // which only writes to fan sensors. 156 std::cerr << info->type << " readPath: " << info->readPath << "\n"; 157 158 if (IOInterfaceType::EXTERNAL == rtype) 159 { 160 std::cerr << "Creating HostSensor: " << name 161 << " path: " << info->readPath << "\n"; 162 163 /* 164 * The reason we handle this as a HostSensor is because it's 165 * not quite pluggable; but maybe it could be. 166 */ 167 auto sensor = HostSensor::createTemp( 168 name, info->timeout, hostSensorBus, info->readPath.c_str(), 169 deferSignals); 170 mgmr.addSensor(info->type, name, std::move(sensor)); 171 } 172 else 173 { 174 wi = std::make_unique<ReadOnlyNoExcept>(); 175 auto sensor = std::make_unique<PluggableSensor>( 176 name, info->timeout, std::move(ri), std::move(wi)); 177 mgmr.addSensor(info->type, name, std::move(sensor)); 178 } 179 } 180 } 181 182 return mgmr; 183 } 184