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