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 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 */ 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 */ 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 */ 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