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