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