1 #include "config.h" 2 3 #include "occ_pass_through.hpp" 4 5 #include "elog-errors.hpp" 6 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <fmt/core.h> 10 #include <unistd.h> 11 12 #include <algorithm> 13 #include <memory> 14 #include <org/open_power/OCC/Device/error.hpp> 15 #include <phosphor-logging/elog.hpp> 16 #include <phosphor-logging/log.hpp> 17 #include <string> 18 19 namespace open_power 20 { 21 namespace occ 22 { 23 24 PassThrough::PassThrough(const char* path) : 25 Iface(utils::getBus(), path), path(path), 26 devicePath(OCC_DEV_PATH + std::to_string((this->path.back() - '0') + 1)), 27 occInstance(this->path.back() - '0'), 28 activeStatusSignal( 29 utils::getBus(), 30 sdbusRule::propertiesChanged(path, "org.open_power.OCC.Status"), 31 std::bind(std::mem_fn(&PassThrough::activeStatusEvent), this, 32 std::placeholders::_1)), 33 occCmd(occInstance, path) 34 { 35 // Nothing to do. 36 } 37 38 std::vector<int32_t> PassThrough::send(std::vector<int32_t> command) 39 { 40 std::vector<int32_t> response{}; 41 42 // OCC only understands [bytes] so need array of bytes. Doing this 43 // because rest-server currently treats all int* as 32 bit integer. 44 std::vector<uint8_t> cmdInBytes, rsp; 45 cmdInBytes.resize(command.size()); 46 47 // Populate uint8_t version of vector. 48 std::transform(command.begin(), command.end(), cmdInBytes.begin(), 49 [](decltype(cmdInBytes)::value_type x) { return x; }); 50 51 rsp = send(cmdInBytes); 52 53 response.resize(rsp.size()); 54 std::transform(rsp.begin(), rsp.end(), response.begin(), 55 [](decltype(response)::value_type x) { return x; }); 56 57 return response; 58 } 59 60 std::vector<uint8_t> PassThrough::send(std::vector<uint8_t> command) 61 { 62 using namespace phosphor::logging; 63 using namespace sdbusplus::org::open_power::OCC::Device::Error; 64 65 std::vector<uint8_t> response{}; 66 67 log<level::DEBUG>( 68 fmt::format("PassThrough::send() Sending 0x{:02X} command to OCC{}", 69 command.front(), occInstance) 70 .c_str()); 71 CmdStatus status = occCmd.send(command, response); 72 if (status == CmdStatus::SUCCESS) 73 { 74 if (response.size() >= 5) 75 { 76 log<level::DEBUG>(fmt::format("PassThrough::send() " 77 "response had {} bytes", 78 response.size()) 79 .c_str()); 80 } 81 else 82 { 83 log<level::ERR>("PassThrough::send() Invalid OCC response"); 84 dump_hex(response); 85 } 86 } 87 else 88 { 89 if (status == CmdStatus::OPEN_FAILURE) 90 { 91 log<level::WARNING>("PassThrough::send() - OCC not active yet"); 92 } 93 else 94 { 95 log<level::ERR>("PassThrough::send() - OCC command failed!"); 96 } 97 } 98 99 return response; 100 } 101 102 // Called at OCC Status change signal 103 void PassThrough::activeStatusEvent(sdbusplus::message::message& msg) 104 { 105 std::string statusInterface; 106 std::map<std::string, std::variant<bool>> msgData; 107 msg.read(statusInterface, msgData); 108 109 auto propertyMap = msgData.find("OccActive"); 110 if (propertyMap != msgData.end()) 111 { 112 // Extract the OccActive property 113 if (std::get<bool>(propertyMap->second)) 114 { 115 occActive = true; 116 } 117 else 118 { 119 occActive = false; 120 } 121 } 122 return; 123 } 124 125 } // namespace occ 126 } // namespace open_power 127