xref: /openbmc/phosphor-fan-presence/control/json/utils/pcie_card_metadata.hpp (revision 4fa67aa12bd73f7d528225f0c3c93c3242bbcc23)
1 /**
2  * Copyright © 2022 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <nlohmann/json.hpp>
19 
20 #include <filesystem>
21 #include <optional>
22 #include <string>
23 #include <variant>
24 #include <vector>
25 
26 namespace phosphor::fan::control::json
27 {
28 
29 /**
30  * @class PCIeCardMetadata
31  *
32  * This class provides the ability for an action to look up a PCIe card's
33  * fan floor index or temp sensor name based on its metadata, which
34  * consists of 4 properties from the PCIeDevice D-Bus interface.
35  *
36  * The metadata is stored in a JSON file, which looks like:
37  *  {
38  *    "cards": [
39  *      {
40  *        "name": "TestCard",
41  *        "device_id": "0x1",
42  *        "vendor_id": "0x2",
43  *        "subsystem_id": "0x3",
44  *        "subsystem_vendor_id": "0x4",
45  *        "floor_index": 3
46  *      },
47  *      ...
48  *    ]
49  *  }
50  *
51  * If the card has a temperature sensor on it, then it doesn't
52  * need a floor index and instead will have:
53  *   "has_temp_sensor": true
54  */
55 class PCIeCardMetadata
56 {
57   public:
58     PCIeCardMetadata() = delete;
59     ~PCIeCardMetadata() = default;
60     PCIeCardMetadata(const PCIeCardMetadata&) = delete;
61     PCIeCardMetadata& operator=(const PCIeCardMetadata&) = delete;
62     PCIeCardMetadata(PCIeCardMetadata&&) = delete;
63     PCIeCardMetadata& operator=(PCIeCardMetadata&&) = delete;
64 
65     /**
66      * @brief Constructor
67      *
68      * @param[in] systemNames - The system names values
69      */
70     explicit PCIeCardMetadata(const std::vector<std::string>& systemNames);
71 
72     /**
73      * @brief Look up a floor index based on a card's metadata
74      *
75      * @param[in] deviceID - Function0DeviceId value
76      * @param[in] vendorID - Function0VendorId value
77      * @param[in] subsystemID - Function0SubsystemId value
78      * @param[in] subsystemVendorID - Function0SubsystemVendorId value
79      *
80      * @return optional<variant<int32, bool>> -
81      *     Either the floor index for that entry, or true saying
82      *     it has a temp sensor.
83      *
84      *     If no entry is found, it will return std::nullopt.
85      */
86     std::optional<std::variant<int32_t, bool>> lookup(
87         uint16_t deviceID, uint16_t vendorID, uint16_t subsystemID,
88         uint16_t subsystemVendorID) const;
89 
90   private:
91     /**
92      * Structure to hold card metadata.
93      */
94     struct Metadata
95     {
96         uint16_t vendorID;
97         uint16_t deviceID;
98         uint16_t subsystemVendorID;
99         uint16_t subsystemID;
100         int32_t floorIndex;
101         bool hasTempSensor;
102 
operator ==phosphor::fan::control::json::PCIeCardMetadata::Metadata103         bool operator==(const Metadata& other)
104         {
105             return (vendorID == other.vendorID) &&
106                    (deviceID == other.deviceID) &&
107                    (subsystemVendorID == other.subsystemVendorID) &&
108                    (subsystemID == other.subsystemID);
109         }
110     };
111 
112     /**
113      * @brief Loads the metadata from JSON files
114      *
115      * It will load a pcie_cards.json file in the default location if it
116      * is present.
117      *
118      * If systemNames isn't empty, it will load the first 'pcie_cards.json'
119      * files it finds in directories based on those names.
120      *
121      * If no valid config files are found it will throw an exception.
122      *
123      * @param[in] systemNames - The system names values
124      */
125     void loadCards(const std::vector<std::string>& systemNames);
126 
127     /**
128      * @brief Loads in the card info from the JSON
129      *
130      * @param[in] json - The JSON containing a cards array
131      */
132     void load(const nlohmann::json& json);
133 
134     /**
135      * @brief Dumps the cards vector for debug
136      */
137     void dump() const;
138 
139     /**
140      * @brief The card metadata
141      */
142     std::vector<Metadata> _cards;
143 };
144 
145 } // namespace phosphor::fan::control::json
146