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 "manualcmds.hpp"
18 
19 #include "control.hpp"
20 #include "dbus_mode.hpp"
21 #include "manual_messages.hpp"
22 
23 #include <ipmid/api.h>
24 
25 #include <sdbusplus/bus.hpp>
26 #include <sdbusplus/message.hpp>
27 
28 #include <map>
29 #include <memory>
30 #include <string>
31 #include <tuple>
32 #include <variant>
33 
34 namespace pid_control
35 {
36 namespace ipmi
37 {
38 
39 static constexpr auto manualProperty = "Manual";
40 static constexpr auto failsafeProperty = "FailSafe";
41 
42 ipmi_ret_t ZoneControlIpmiHandler::getFailsafeModeState(const uint8_t* reqBuf,
43                                                         uint8_t* replyBuf,
44                                                         size_t* dataLen)
45 {
46     bool current;
47 
48     if (*dataLen < sizeof(struct FanCtrlRequest))
49     {
50         return IPMI_CC_INVALID;
51     }
52 
53     const auto request =
54         reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
55 
56     ipmi_ret_t rc =
57         _control->getFanCtrlProperty(request->zone, &current, failsafeProperty);
58     if (rc)
59     {
60         return rc;
61     }
62 
63     *replyBuf = (uint8_t)current;
64     *dataLen = sizeof(uint8_t);
65     return IPMI_CC_OK;
66 }
67 
68 /*
69  * <method name="GetAll">
70  *   <arg name="interface" direction="in" type="s"/>
71  *   <arg name="properties" direction="out" type="a{sv}"/>
72  * </method>
73  */
74 ipmi_ret_t ZoneControlIpmiHandler::getManualModeState(const uint8_t* reqBuf,
75                                                       uint8_t* replyBuf,
76                                                       size_t* dataLen)
77 {
78     bool current;
79 
80     if (*dataLen < sizeof(struct FanCtrlRequest))
81     {
82         return IPMI_CC_INVALID;
83     }
84 
85     const auto request =
86         reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
87 
88     ipmi_ret_t rc =
89         _control->getFanCtrlProperty(request->zone, &current, manualProperty);
90     if (rc)
91     {
92         return rc;
93     }
94 
95     *replyBuf = (uint8_t)current;
96     *dataLen = sizeof(uint8_t);
97     return IPMI_CC_OK;
98 }
99 
100 /*
101  * <method name="Set">
102  *   <arg name="interface" direction="in" type="s"/>
103  *   <arg name="property" direction="in" type="s"/>
104  *   <arg name="value" direction="in" type="v"/>
105  * </method>
106  */
107 ipmi_ret_t ZoneControlIpmiHandler::setManualModeState(
108     const uint8_t* reqBuf, [[maybe_unused]] uint8_t* replyBuf, size_t* dataLen)
109 {
110     if (*dataLen < sizeof(struct FanCtrlRequestSet))
111     {
112         return IPMI_CC_INVALID;
113     }
114 
115     const auto request =
116         reinterpret_cast<const struct FanCtrlRequestSet*>(&reqBuf[0]);
117 
118     /* 0 is false, 1 is true */
119     ipmi_ret_t rc = _control->setFanCtrlProperty(
120         request->zone, static_cast<bool>(request->value), manualProperty);
121     return rc;
122 }
123 
124 /* Three command packages: get, set true, set false */
125 ipmi_ret_t manualModeControl(ZoneControlIpmiHandler* handler,
126                              [[maybe_unused]] ipmi_cmd_t cmd,
127                              const uint8_t* reqBuf, uint8_t* replyCmdBuf,
128                              size_t* dataLen)
129 {
130     // FanCtrlRequest is the smaller of the requests, so it's at a minimum.
131     if (*dataLen < sizeof(struct FanCtrlRequest))
132     {
133         return IPMI_CC_INVALID;
134     }
135 
136     const auto request =
137         reinterpret_cast<const struct FanCtrlRequest*>(&reqBuf[0]);
138 
139     ipmi_ret_t rc = IPMI_CC_OK;
140 
141     switch (request->command)
142     {
143         case getControlState:
144             return handler->getManualModeState(reqBuf, replyCmdBuf, dataLen);
145         case setControlState:
146             return handler->setManualModeState(reqBuf, replyCmdBuf, dataLen);
147         case getFailsafeState:
148             return handler->getFailsafeModeState(reqBuf, replyCmdBuf, dataLen);
149         default:
150             rc = IPMI_CC_INVALID;
151     }
152 
153     return rc;
154 }
155 
156 } // namespace ipmi
157 } // namespace pid_control
158