1 #include <memory> 2 #include <algorithm> 3 #include <fcntl.h> 4 #include <errno.h> 5 #include <phosphor-logging/log.hpp> 6 #include "occ_pass_through.hpp" 7 #include "occ_finder.hpp" 8 namespace open_power 9 { 10 namespace occ 11 { 12 namespace pass_through 13 { 14 15 void run() 16 { 17 auto bus = sdbusplus::bus::new_default(); 18 sdbusplus::server::manager::manager objManager(bus, 19 OCC_PASS_THROUGH_ROOT); 20 21 std::vector<std::unique_ptr<PassThrough>> objects; 22 auto occs = open_power::occ::finder::get(); 23 24 for (const auto& occ : occs) 25 { 26 auto occPassThrough = object(occ); 27 objects.emplace_back( 28 std::make_unique<PassThrough>(bus, occPassThrough.c_str())); 29 } 30 bus.request_name(OCC_PASS_THROUGH_BUSNAME); 31 32 while (true) 33 { 34 bus.process_discard(); 35 bus.wait(); 36 } 37 } 38 39 PassThrough::PassThrough( 40 sdbusplus::bus::bus& bus, 41 const char* path) : 42 Iface(bus, path), 43 path(path), 44 fd(openDevice()) 45 { 46 // Nothing to do. 47 } 48 49 int PassThrough::openDevice() 50 { 51 // Device instance number starts from 1. 52 devicePath.append(std::to_string((this->path.back() - '0') + 1)); 53 54 int fd = open(devicePath.c_str(), O_RDWR | O_NONBLOCK); 55 if (fd < 0) 56 { 57 // This is for completion. This is getting replaced by elog 58 // in the next commit 59 throw std::runtime_error("Error opening " + devicePath); 60 } 61 return fd; 62 } 63 64 std::vector<int32_t> PassThrough::send(std::vector<int32_t> command) 65 { 66 using namespace phosphor::logging; 67 68 std::vector<int32_t> response {}; 69 70 // Amester packs data in 4 bytes 71 ssize_t size = command.size() * sizeof(int32_t); 72 auto rc = write((fd)(), command.data(), size); 73 if (rc < 0 || (rc != size)) 74 { 75 log<level::ERR>("Error writing to OCC"); 76 77 // In the next commit, it will have exceptions. 78 return response; 79 } 80 81 // Now read the response. This would be the content of occ-sram 82 while(1) 83 { 84 errno = 0; 85 int32_t data {}; 86 auto len = read((fd)(), &data, sizeof(data)); 87 if (len > 0) 88 { 89 response.emplace_back(data); 90 } 91 else if (len < 0 && errno == EAGAIN) 92 { 93 // We may have data coming still 94 continue; 95 } 96 else if (len == 0) 97 { 98 // We have read all that we can. 99 break; 100 } 101 else 102 { 103 // Will have exception in the next commit. 104 log<level::ERR>("Error reading from OCC"); 105 break; 106 } 107 } 108 109 return response; 110 } 111 112 113 } // namespace pass_through 114 } // namespace occ 115 } // namespace open_power 116