1 #pragma once 2 3 #include "sensorhandler.hpp" 4 5 #include <cmath> 6 #include <ipmid/api.hpp> 7 #include <ipmid/types.hpp> 8 #include <ipmid/utils.hpp> 9 #include <sdbusplus/message/types.hpp> 10 11 namespace ipmi 12 { 13 namespace sensor 14 { 15 16 using Assertion = uint16_t; 17 using Deassertion = uint16_t; 18 using AssertionSet = std::pair<Assertion, Deassertion>; 19 20 using Service = std::string; 21 using Path = std::string; 22 using Interface = std::string; 23 24 using ServicePath = std::pair<Path, Service>; 25 26 using Interfaces = std::vector<Interface>; 27 28 using MapperResponseType = std::map<Path, std::map<Service, Interfaces>>; 29 30 /** @brief get the D-Bus service and service path 31 * @param[in] bus - The Dbus bus object 32 * @param[in] interface - interface to the service 33 * @param[in] path - interested path in the list of objects 34 * @return pair of service path and service 35 */ 36 ServicePath getServiceAndPath(sdbusplus::bus::bus& bus, 37 const std::string& interface, 38 const std::string& path = std::string()); 39 40 /** @brief Make assertion set from input data 41 * @param[in] cmdData - Input sensor data 42 * @return pair of assertion and deassertion set 43 */ 44 AssertionSet getAssertionSet(const SetSensorReadingReq& cmdData); 45 46 /** @brief send the message to DBus 47 * @param[in] msg - message to send 48 * @return failure status in IPMI error code 49 */ 50 ipmi_ret_t updateToDbus(IpmiUpdateData& msg); 51 52 namespace get 53 { 54 55 /** @brief Populate sensor name from the D-Bus property associated with the 56 * sensor. In the example entry from the yaml, the name of the D-bus 57 * property "AttemptsLeft" is the sensor name. 58 * 59 * 0x07: 60 * sensorType: 195 61 * path: /xyz/openbmc_project/state/host0 62 * sensorReadingType: 0x6F 63 * serviceInterface: org.freedesktop.DBus.Properties 64 * readingType: readingAssertion 65 * sensorNamePattern: nameProperty 66 * interfaces: 67 * xyz.openbmc_project.Control.Boot.RebootAttempts: 68 * AttemptsLeft: 69 * Offsets: 70 * 0xFF: 71 * type: uint32_t 72 * 73 * 74 * @param[in] sensorInfo - Dbus info related to sensor. 75 * 76 * @return On success return the sensor name for the sensor. 77 */ 78 inline SensorName nameProperty(const Info& sensorInfo) 79 { 80 return sensorInfo.propertyInterfaces.begin()->second.begin()->first; 81 } 82 83 /** @brief Populate sensor name from the D-Bus object associated with the 84 * sensor. If the object path is /system/chassis/motherboard/dimm0 then 85 * the leaf dimm0 is considered as the sensor name. 86 * 87 * @param[in] sensorInfo - Dbus info related to sensor. 88 * 89 * @return On success return the sensor name for the sensor. 90 */ 91 inline SensorName nameLeaf(const Info& sensorInfo) 92 { 93 return sensorInfo.sensorPath.substr( 94 sensorInfo.sensorPath.find_last_of('/') + 1, 95 sensorInfo.sensorPath.length()); 96 } 97 98 /** @brief Populate sensor name from the D-Bus object associated with the 99 * sensor. If the object path is /system/chassis/motherboard/cpu0/core0 100 * then the sensor name is cpu0_core0. The leaf and the parent is put 101 * together to get the sensor name. 102 * 103 * @param[in] sensorInfo - Dbus info related to sensor. 104 * 105 * @return On success return the sensor name for the sensor. 106 */ 107 SensorName nameParentLeaf(const Info& sensorInfo); 108 109 /** 110 * @brief Helper function to map the dbus info to sensor's assertion status 111 * for the get sensor reading command. 112 * 113 * @param[in] sensorInfo - Dbus info related to sensor. 114 * @param[in] path - Dbus object path. 115 * @param[in] interface - Dbus interface. 116 * 117 * @return Response for get sensor reading command. 118 */ 119 GetSensorResponse mapDbusToAssertion(const Info& sensorInfo, 120 const InstancePath& path, 121 const DbusInterface& interface); 122 123 /** 124 * @brief Map the Dbus info to sensor's assertion status in the Get sensor 125 * reading command response. 126 * 127 * @param[in] sensorInfo - Dbus info related to sensor. 128 * 129 * @return Response for get sensor reading command. 130 */ 131 GetSensorResponse assertion(const Info& sensorInfo); 132 133 /** 134 * @brief Maps the Dbus info to the reading field in the Get sensor reading 135 * command response. 136 * 137 * @param[in] sensorInfo - Dbus info related to sensor. 138 * 139 * @return Response for get sensor reading command. 140 */ 141 GetSensorResponse eventdata2(const Info& sensorInfo); 142 143 /** 144 * @brief readingAssertion is a case where the entire assertion state field 145 * serves as the sensor value. 146 * 147 * @tparam T - type of the dbus property related to sensor. 148 * @param[in] sensorInfo - Dbus info related to sensor. 149 * 150 * @return Response for get sensor reading command. 151 */ 152 template <typename T> 153 GetSensorResponse readingAssertion(const Info& sensorInfo) 154 { 155 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 156 GetSensorResponse response{}; 157 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data()); 158 159 auto service = ipmi::getService(bus, sensorInfo.sensorInterface, 160 sensorInfo.sensorPath); 161 162 auto propValue = ipmi::getDbusProperty( 163 bus, service, sensorInfo.sensorPath, 164 sensorInfo.propertyInterfaces.begin()->first, 165 sensorInfo.propertyInterfaces.begin()->second.begin()->first); 166 167 setAssertionBytes(static_cast<uint16_t>(std::get<T>(propValue)), 168 responseData); 169 170 return response; 171 } 172 173 /** @brief Map the Dbus info to the reading field in the Get sensor reading 174 * command response 175 * 176 * @tparam T - type of the dbus property related to sensor. 177 * @param[in] sensorInfo - Dbus info related to sensor. 178 * 179 * @return Response for get sensor reading command. 180 */ 181 template <typename T> 182 GetSensorResponse readingData(const Info& sensorInfo) 183 { 184 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; 185 GetSensorResponse response{}; 186 auto responseData = reinterpret_cast<GetReadingResponse*>(response.data()); 187 188 enableScanning(responseData); 189 190 auto service = ipmi::getService(bus, sensorInfo.sensorInterface, 191 sensorInfo.sensorPath); 192 193 auto propValue = ipmi::getDbusProperty( 194 bus, service, sensorInfo.sensorPath, 195 sensorInfo.propertyInterfaces.begin()->first, 196 sensorInfo.propertyInterfaces.begin()->second.begin()->first); 197 198 double value = std::get<T>(propValue) * 199 std::pow(10, sensorInfo.scale - sensorInfo.exponentR); 200 201 auto rawData = static_cast<uint8_t>((value - sensorInfo.scaledOffset) / 202 sensorInfo.coefficientM); 203 204 setReading(rawData, responseData); 205 206 return response; 207 } 208 209 } // namespace get 210 211 namespace set 212 { 213 214 /** @brief Make a DBus message for a Dbus call 215 * @param[in] updateInterface - Interface name 216 * @param[in] sensorPath - Path of the sensor 217 * @param[in] command - command to be executed 218 * @param[in] sensorInterface - DBus interface of sensor 219 * @return a dbus message 220 */ 221 IpmiUpdateData makeDbusMsg(const std::string& updateInterface, 222 const std::string& sensorPath, 223 const std::string& command, 224 const std::string& sensorInterface); 225 226 /** @brief Update d-bus based on assertion type sensor data 227 * @param[in] cmdData - input sensor data 228 * @param[in] sensorInfo - sensor d-bus info 229 * @return a IPMI error code 230 */ 231 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, 232 const Info& sensorInfo); 233 234 /** @brief Update d-bus based on a reading assertion 235 * @tparam T - type of d-bus property mapping this sensor 236 * @param[in] cmdData - input sensor data 237 * @param[in] sensorInfo - sensor d-bus info 238 * @return a IPMI error code 239 */ 240 template <typename T> 241 ipmi_ret_t readingAssertion(const SetSensorReadingReq& cmdData, 242 const Info& sensorInfo) 243 { 244 auto msg = 245 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath, 246 "Set", sensorInfo.sensorInterface); 247 248 const auto& interface = sensorInfo.propertyInterfaces.begin(); 249 msg.append(interface->first); 250 for (const auto& property : interface->second) 251 { 252 msg.append(property.first); 253 std::variant<T> value = 254 (cmdData.assertOffset8_14 << 8) | cmdData.assertOffset0_7; 255 msg.append(value); 256 } 257 return updateToDbus(msg); 258 } 259 260 /** @brief Update d-bus based on a discrete reading 261 * @param[in] cmdData - input sensor data 262 * @param[in] sensorInfo - sensor d-bus info 263 * @return an IPMI error code 264 */ 265 template <typename T> 266 ipmi_ret_t readingData(const SetSensorReadingReq& cmdData, 267 const Info& sensorInfo) 268 { 269 T raw_value = 270 (sensorInfo.coefficientM * cmdData.reading) + sensorInfo.scaledOffset; 271 272 raw_value *= std::pow(10, sensorInfo.exponentR - sensorInfo.scale); 273 274 auto msg = 275 makeDbusMsg("org.freedesktop.DBus.Properties", sensorInfo.sensorPath, 276 "Set", sensorInfo.sensorInterface); 277 278 const auto& interface = sensorInfo.propertyInterfaces.begin(); 279 msg.append(interface->first); 280 281 for (const auto& property : interface->second) 282 { 283 msg.append(property.first); 284 std::variant<T> value = raw_value; 285 msg.append(value); 286 } 287 return updateToDbus(msg); 288 } 289 290 /** @brief Update d-bus based on eventdata type sensor data 291 * @param[in] cmdData - input sensor data 292 * @param[in] sensorInfo - sensor d-bus info 293 * @return a IPMI error code 294 */ 295 ipmi_ret_t eventdata(const SetSensorReadingReq& cmdData, const Info& sensorInfo, 296 uint8_t data); 297 298 /** @brief Update d-bus based on eventdata1 type sensor data 299 * @param[in] cmdData - input sensor data 300 * @param[in] sensorInfo - sensor d-bus info 301 * @return a IPMI error code 302 */ 303 inline ipmi_ret_t eventdata1(const SetSensorReadingReq& cmdData, 304 const Info& sensorInfo) 305 { 306 return eventdata(cmdData, sensorInfo, cmdData.eventData1); 307 } 308 309 /** @brief Update d-bus based on eventdata2 type sensor data 310 * @param[in] cmdData - input sensor data 311 * @param[in] sensorInfo - sensor d-bus info 312 * @return a IPMI error code 313 */ 314 inline ipmi_ret_t eventdata2(const SetSensorReadingReq& cmdData, 315 const Info& sensorInfo) 316 { 317 return eventdata(cmdData, sensorInfo, cmdData.eventData2); 318 } 319 320 /** @brief Update d-bus based on eventdata3 type sensor data 321 * @param[in] cmdData - input sensor data 322 * @param[in] sensorInfo - sensor d-bus info 323 * @return a IPMI error code 324 */ 325 inline ipmi_ret_t eventdata3(const SetSensorReadingReq& cmdData, 326 const Info& sensorInfo) 327 { 328 return eventdata(cmdData, sensorInfo, cmdData.eventData3); 329 } 330 331 } // namespace set 332 333 namespace notify 334 { 335 336 /** @brief Make a DBus message for a Dbus call 337 * @param[in] updateInterface - Interface name 338 * @param[in] sensorPath - Path of the sensor 339 * @param[in] command - command to be executed 340 * @param[in] sensorInterface - DBus interface of sensor 341 * @return a dbus message 342 */ 343 IpmiUpdateData makeDbusMsg(const std::string& updateInterface, 344 const std::string& sensorPath, 345 const std::string& command, 346 const std::string& sensorInterface); 347 348 /** @brief Update d-bus based on assertion type sensor data 349 * @param[in] interfaceMap - sensor interface 350 * @param[in] cmdData - input sensor data 351 * @param[in] sensorInfo - sensor d-bus info 352 * @return a IPMI error code 353 */ 354 ipmi_ret_t assertion(const SetSensorReadingReq& cmdData, 355 const Info& sensorInfo); 356 357 } // namespace notify 358 359 namespace inventory 360 { 361 362 namespace get 363 { 364 365 /** 366 * @brief Map the Dbus info to sensor's assertion status in the Get sensor 367 * reading command response. 368 * 369 * @param[in] sensorInfo - Dbus info related to sensor. 370 * 371 * @return Response for get sensor reading command. 372 */ 373 GetSensorResponse assertion(const Info& sensorInfo); 374 375 } // namespace get 376 377 } // namespace inventory 378 } // namespace sensor 379 } // namespace ipmi 380