/** * Copyright 2017 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include /* Configuration. */ #include "conf.hpp" #include "dbus/dbuspassive.hpp" #include "dbus/dbuswrite.hpp" #include "errors/exception.hpp" #include "interfaces.hpp" #include "notimpl/readonly.hpp" #include "notimpl/writeonly.hpp" #include "sensors/builder.hpp" #include "sensors/host.hpp" #include "sensors/manager.hpp" #include "sensors/pluggable.hpp" #include "sysfs/sysfsread.hpp" #include "sysfs/sysfswrite.hpp" #include "util.hpp" static constexpr bool deferSignals = true; static DbusHelper helper; SensorManager buildSensors(const std::map& config) { SensorManager mgmr; auto& HostSensorBus = mgmr.getHostBus(); auto& PassiveListeningBus = mgmr.getPassiveBus(); for (const auto& it : config) { std::unique_ptr ri; std::unique_ptr wi; std::string name = it.first; const struct SensorConfig* info = &it.second; std::cerr << "Sensor: " << name << " " << info->type << " "; std::cerr << info->readpath << " " << info->writepath << "\n"; IOInterfaceType rtype = getReadInterfaceType(info->readpath); IOInterfaceType wtype = getWriteInterfaceType(info->writepath); // fan sensors can be ready any way and written others. // fan sensors are the only sensors this is designed to write. // Nothing here should be write-only, although, in theory a fan could // be. I'm just not sure how that would fit together. // TODO(venture): It should check with the ObjectMapper to check if // that sensor exists on the Dbus. switch (rtype) { case IOInterfaceType::DBUSPASSIVE: ri = DbusPassive::createDbusPassive(PassiveListeningBus, info->type, name, &helper); if (ri == nullptr) { throw SensorBuildException( "Failed to create dbus passive sensor: " + name + " of type: " + info->type); } break; case IOInterfaceType::EXTERNAL: // These are a special case for read-only. break; case IOInterfaceType::SYSFS: ri = std::make_unique(info->readpath); break; default: ri = std::make_unique(); break; } if (info->type == "fan") { switch (wtype) { case IOInterfaceType::SYSFS: if (info->max > 0) { wi = std::make_unique( info->writepath, info->min, info->max); } else { wi = std::make_unique(info->writepath, info->min, info->max); } break; case IOInterfaceType::DBUSACTIVE: if (info->max > 0) { wi = DbusWritePercent::createDbusWrite( info->writepath, info->min, info->max, helper); } else { wi = DbusWrite::createDbusWrite( info->writepath, info->min, info->max, helper); } if (wi == nullptr) { throw SensorBuildException( "Unable to create write dbus interface for path: " + info->writepath); } break; default: wi = std::make_unique(); break; } auto sensor = std::make_unique( name, info->timeout, std::move(ri), std::move(wi)); mgmr.addSensor(info->type, name, std::move(sensor)); } else if (info->type == "temp" || info->type == "margin") { // These sensors are read-only, but only for this application // which only writes to fan sensors. std::cerr << info->type << " readpath: " << info->readpath << "\n"; if (IOInterfaceType::EXTERNAL == rtype) { std::cerr << "Creating HostSensor: " << name << " path: " << info->readpath << "\n"; /* * The reason we handle this as a HostSensor is because it's * not quite pluggable; but maybe it could be. */ auto sensor = HostSensor::createTemp( name, info->timeout, HostSensorBus, info->readpath.c_str(), deferSignals); mgmr.addSensor(info->type, name, std::move(sensor)); } else { wi = std::make_unique(); auto sensor = std::make_unique( name, info->timeout, std::move(ri), std::move(wi)); mgmr.addSensor(info->type, name, std::move(sensor)); } } } return mgmr; }