1 /**
2  * Copyright © 2017 IBM Corporation
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 #include "config.h"
17 
18 #ifndef CONTROL_USE_JSON
19 #include "argument.hpp"
20 #include "manager.hpp"
21 #else
22 #include "json/manager.hpp"
23 #endif
24 #include "sdbusplus.hpp"
25 
26 #include <phosphor-logging/log.hpp>
27 #include <sdbusplus/bus.hpp>
28 #include <sdeventplus/event.hpp>
29 #include <sdeventplus/source/signal.hpp>
30 #include <stdplus/signal.hpp>
31 
32 using namespace phosphor::fan::control;
33 using namespace phosphor::logging;
34 
35 int main(int argc, char* argv[])
36 {
37     auto event = sdeventplus::Event::get_default();
38 
39 #ifndef CONTROL_USE_JSON
40     phosphor::fan::util::ArgumentParser args(argc, argv);
41     if (argc != 2)
42     {
43         args.usage(argv);
44         return 1;
45     }
46 
47     Mode mode;
48 
49     if (args["init"] == "true")
50     {
51         mode = Mode::init;
52     }
53     else if (args["control"] == "true")
54     {
55         mode = Mode::control;
56     }
57     else
58     {
59         args.usage(argv);
60         return 1;
61     }
62 #endif
63 
64     // Attach the event object to the bus object so we can
65     // handle both sd_events (for the timers) and dbus signals.
66     phosphor::fan::util::SDBusPlus::getBus().attach_event(
67         event.get(), SD_EVENT_PRIORITY_NORMAL);
68 
69     try
70     {
71 #ifdef CONTROL_USE_JSON
72         json::Manager manager(event);
73 
74         // Handle loading fan control's config file(s)
75         phosphor::fan::JsonConfig config(
76             std::bind(&json::Manager::load, &manager));
77 
78         // Enable SIGHUP handling to reload JSON configs
79         stdplus::signal::block(SIGHUP);
80         sdeventplus::source::Signal signal(
81             event, SIGHUP,
82             std::bind(&json::Manager::sighupHandler, &manager,
83                       std::placeholders::_1, std::placeholders::_2));
84 
85         phosphor::fan::util::SDBusPlus::getBus().request_name(CONTROL_BUSNAME);
86 
87         // TODO - Set power state to on until fan control services updated
88         manager.powerStateChanged(true);
89 #else
90         Manager manager(phosphor::fan::util::SDBusPlus::getBus(), event, mode);
91 
92         // Init mode will just set fans to max and delay
93         if (mode == Mode::init)
94         {
95             manager.doInit(event);
96             return 0;
97         }
98 #endif
99         return event.loop();
100     }
101     // Log the useful metadata on these exceptions and let the app
102     // return 1 so it is restarted without a core dump.
103     catch (phosphor::fan::util::DBusServiceError& e)
104     {
105         log<level::ERR>("Uncaught DBus service lookup failure exception",
106                         entry("PATH=%s", e.path.c_str()),
107                         entry("INTERFACE=%s", e.interface.c_str()));
108     }
109     catch (phosphor::fan::util::DBusMethodError& e)
110     {
111         log<level::ERR>("Uncaught DBus method failure exception",
112                         entry("BUSNAME=%s", e.busName.c_str()),
113                         entry("PATH=%s", e.path.c_str()),
114                         entry("INTERFACE=%s", e.interface.c_str()),
115                         entry("METHOD=%s", e.method.c_str()));
116     }
117     catch (phosphor::fan::util::DBusPropertyError& e)
118     {
119         log<level::ERR>("Uncaught DBus property access failure exception",
120                         entry("BUSNAME=%s", e.busName.c_str()),
121                         entry("PATH=%s", e.path.c_str()),
122                         entry("INTERFACE=%s", e.interface.c_str()),
123                         entry("PROPERTY=%s", e.property.c_str()));
124     }
125 
126     return 1;
127 }
128