1 #pragma once 2 3 #include <string> 4 #include <cstring> 5 #include <map> 6 #include <vector> 7 #include <experimental/filesystem> 8 #include <unistd.h> 9 #include <sdbusplus/bus.hpp> 10 #include <functional> 11 #include <sdbusplus/server/object.hpp> 12 #include <org/open_power/OCC/PassThrough/server.hpp> 13 #include "config.h" 14 #include "file.hpp" 15 16 namespace sdbusRule = sdbusplus::bus::match::rules; 17 18 namespace open_power 19 { 20 namespace occ 21 { 22 namespace pass_through 23 { 24 25 class PassThrough; 26 27 namespace manager 28 { 29 30 /** @class Manager 31 * @brief Builds and manages OCC pass-through objects 32 */ 33 struct Manager 34 { 35 public: 36 Manager() = delete; 37 Manager(const Manager&) = delete; 38 Manager& operator=(const Manager&) = delete; 39 Manager(Manager&&) = default; 40 Manager& operator=(Manager&&) = default; 41 ~Manager() = default; 42 43 /** @brief Ctor - Add OCC pass-through objects on the bus. Create 44 * OCC objects when corresponding CPU inventory is created. 45 * @param[in] bus - handle to the bus 46 */ 47 Manager(sdbusplus::bus::bus& bus): 48 bus(bus) 49 { 50 for (auto id = 0; id < MAX_CPUS; ++id) 51 { 52 auto path = std::string(CPU_PATH) + std::to_string(id); 53 cpuMatches.emplace_back( 54 bus, 55 sdbusRule::interfacesAdded() + 56 sdbusRule::argNpath(0, path), 57 std::bind(std::mem_fn(&Manager::cpuCreated), 58 this, std::placeholders::_1)); 59 } 60 } 61 62 /** @brief Callback that responds to cpu creation in the inventory - 63 * by creating the occ passthrough object. 64 * 65 * @param[in] msg - bus message 66 * 67 * @returns 0 to indicate success 68 */ 69 int cpuCreated(sdbusplus::message::message& msg) 70 { 71 namespace fs = std::experimental::filesystem; 72 73 sdbusplus::message::object_path o; 74 msg.read(o); 75 fs::path cpuPath(std::string(std::move(o))); 76 auto cpu = cpuPath.filename(); 77 78 auto occPath = fs::path(OCC_PASS_THROUGH_ROOT); 79 std::string name{cpu.c_str()}; 80 auto index = name.find(CPU_NAME); 81 name.replace(index, std::strlen(CPU_NAME), OCC_NAME); 82 occPath /= name; 83 84 objects.emplace_back( 85 std::make_unique<PassThrough>( 86 bus, 87 occPath.c_str())); 88 89 return 0; 90 } 91 92 private: 93 /** @brief reference to the bus */ 94 sdbusplus::bus::bus& bus; 95 96 /** @brief OCC pass-through objects */ 97 std::vector<std::unique_ptr<PassThrough>> objects; 98 99 /** @brief sbdbusplus match objects */ 100 std::vector<sdbusplus::bus::match_t> cpuMatches; 101 }; 102 103 } // namespace manager 104 105 106 using Iface = sdbusplus::server::object::object< 107 sdbusplus::org::open_power::OCC::server::PassThrough>; 108 109 /** @class PassThrough 110 * @brief Implements org.open_power.OCC.PassThrough 111 */ 112 class PassThrough : public Iface 113 { 114 public: 115 PassThrough() = delete; 116 ~PassThrough() = default; 117 PassThrough(const PassThrough&) = delete; 118 PassThrough& operator=(const PassThrough&) = delete; 119 PassThrough(PassThrough&&) = default; 120 PassThrough& operator=(PassThrough&&) = default; 121 122 /** @brief Ctor to put pass-through d-bus object on the bus 123 * @param[in] bus - Bus to attach to 124 * @param[in] path - Path to attach at 125 */ 126 PassThrough(sdbusplus::bus::bus& bus, 127 const char* path); 128 129 /** @brief Pass through command to OCC 130 * @param[in] command - command to pass-through 131 * @returns OCC response as an array 132 */ 133 std::vector<std::int32_t> 134 send(std::vector<std::int32_t> command) override; 135 136 private: 137 /** @brief Pass-through occ path on the bus */ 138 std::string path; 139 140 /** @brief OCC device path 141 * For now, here is the hard-coded mapping until 142 * the udev rule is in. 143 * occ0 --> /dev/occfifo1 144 * occ1 --> /dev/occfifo2 145 * ... 146 */ 147 std::string devicePath = "/dev/occ"; 148 149 /** @brief File descriptor manager */ 150 FileDescriptor fd; 151 152 /** Opens devicePath and returns file descritor */ 153 int openDevice(); 154 }; 155 156 } // namespace pass_through 157 } // namespace occ 158 } // namespace open_power 159