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