1 #pragma once
2 
3 #include "average.hpp"
4 #include "maximum.hpp"
5 #include "pmbus.hpp"
6 #include "record_manager.hpp"
7 #include "types.hpp"
8 #include "util.hpp"
9 #include "utility.hpp"
10 
11 #include <gpiod.hpp>
12 #include <sdbusplus/bus/match.hpp>
13 
14 #include <filesystem>
15 #include <stdexcept>
16 
17 namespace phosphor::power::psu
18 {
19 
20 #if IBM_VPD
21 // PMBus device driver "file name" to read for CCIN value.
22 constexpr auto CCIN = "ccin";
23 constexpr auto PART_NUMBER = "part_number";
24 constexpr auto FRU_NUMBER = "fru";
25 constexpr auto SERIAL_HEADER = "header";
26 constexpr auto SERIAL_NUMBER = "serial_number";
27 constexpr auto FW_VERSION = "fw_version";
28 
29 // The D-Bus property name to update with the CCIN value.
30 constexpr auto MODEL_PROP = "Model";
31 constexpr auto PN_PROP = "PartNumber";
32 constexpr auto SPARE_PN_PROP = "SparePartNumber";
33 constexpr auto SN_PROP = "SerialNumber";
34 constexpr auto VERSION_PROP = "Version";
35 
36 // ipzVPD Keyword sizes
37 static constexpr auto FL_KW_SIZE = 20;
38 #endif
39 
40 constexpr auto LOG_LIMIT = 3;
41 constexpr auto DEGLITCH_LIMIT = 3;
42 
43 /**
44  * @class PowerSupply
45  * Represents a PMBus power supply device.
46  */
47 class PowerSupply
48 {
49   public:
50     PowerSupply() = delete;
51     PowerSupply(const PowerSupply&) = delete;
52     PowerSupply(PowerSupply&&) = delete;
53     PowerSupply& operator=(const PowerSupply&) = delete;
54     PowerSupply& operator=(PowerSupply&&) = delete;
55     ~PowerSupply() = default;
56 
57     /**
58      * @param[in] invpath - String for inventory path to use
59      * @param[in] i2cbus - The bus number this power supply is on
60      * @param[in] i2caddr - The 16-bit I2C address of the power supply
61      * @param[in] driver - i2c driver name for power supply
62      * @param[in] gpioLineName - The gpio-line-name to read for presence. See
63      * https://github.com/openbmc/docs/blob/master/designs/device-tree-gpio-naming.md
64      */
65     PowerSupply(sdbusplus::bus::bus& bus, const std::string& invpath,
66                 std::uint8_t i2cbus, const std::uint16_t i2caddr,
67                 const std::string& driver, const std::string& gpioLineName);
68 
69     phosphor::pmbus::PMBusBase& getPMBus()
70     {
71         return *pmbusIntf;
72     }
73 
74     GPIOInterfaceBase* getPresenceGPIO()
75     {
76         return presenceGPIO.get();
77     }
78 
79     std::string getPresenceGPIOName() const
80     {
81         if (presenceGPIO != nullptr)
82         {
83             return presenceGPIO->getName();
84         }
85         else
86         {
87             return std::string();
88         }
89     }
90 
91     /**
92      * Power supply specific function to analyze for faults/errors.
93      *
94      * Various PMBus status bits will be checked for fault conditions.
95      * If a certain fault bits are on, the appropriate error will be
96      * committed.
97      */
98     void analyze();
99 
100     /**
101      * Write PMBus ON_OFF_CONFIG
102      *
103      * This function will be called to cause the PMBus device driver to send the
104      * ON_OFF_CONFIG command. Takes one byte of data.
105      *
106      * @param[in] data - The ON_OFF_CONFIG data byte mask.
107      */
108     void onOffConfig(uint8_t data);
109 
110     /**
111      * Clears all the member variables that indicate if a fault bit was seen as
112      * on in the STATUS_WORD or STATUS_MFR_SPECIFIC response.
113      */
114     void clearFaultFlags()
115     {
116         inputFault = 0;
117         mfrFault = 0;
118         statusMFR = 0;
119         vinUVFault = 0;
120         cmlFault = 0;
121         voutOVFault = 0;
122         ioutOCFault = 0;
123         voutUVFault = 0;
124         fanFault = 0;
125         tempFault = 0;
126         pgoodFault = 0;
127         psKillFault = 0;
128         ps12VcsFault = 0;
129         psCS12VFault = 0;
130     }
131 
132     /**
133      * @brief Function to specifically clear VIN_UV/OFF fault(s).
134      *
135      * The PMBus HWMON device driver has various alarm "files" to read out of
136      * sysfs. Reading those files will indicate if various alarms are active or
137      * not, and then specifically clear those faults that go with that alarm.
138      *
139      * The VIN_UV fault, indicated in STATUS_INPUT, goes with in1_lcrit_alarm.
140      * When a VIN_UV fault occurs, the "Unit Off For Insufficient Input Voltage"
141      * may also be active. Reading in1_lcrit_alarm should clear both fault bits,
142      * resulting in the corresponding fault bits in STATUS_WORD also clearing.
143      *
144      * See: https://www.kernel.org/doc/html/latest/hwmon/pmbus.html
145      */
146     void clearVinUVFault();
147 
148     /**
149      * Write PMBus CLEAR_FAULTS
150      *
151      * This function will be called in various situations in order to clear
152      * any fault status bits that may have been set, in order to start over
153      * with a clean state. Presence changes and power state changes will
154      * want to clear any faults logged.
155      */
156     void clearFaults();
157 
158     /**
159      * @brief Adds properties to the inventory.
160      *
161      * Reads the values from the device and writes them to the
162      * associated power supply D-Bus inventory object.
163      *
164      * This needs to be done on startup, and each time the presence
165      * state changes.
166      *
167      * Properties added:
168      * - Serial Number
169      * - Part Number
170      * - CCIN (Customer Card Identification Number) - added as the Model
171      * - Firmware version
172      */
173     void updateInventory();
174 
175     /**
176      * @brief Accessor function to indicate present status
177      */
178     bool isPresent() const
179     {
180         return present;
181     }
182 
183     /**
184      * @brief Returns the last read value from STATUS_WORD.
185      */
186     uint64_t getStatusWord() const
187     {
188         return statusWord;
189     }
190 
191     /**
192      * @brief Returns the last read value from STATUS_INPUT.
193      */
194     uint64_t getStatusInput() const
195     {
196         return statusInput;
197     }
198 
199     /**
200      * @brief Returns the last read value from STATUS_MFR.
201      */
202     uint64_t getMFRFault() const
203     {
204         return statusMFR;
205     }
206 
207     /**
208      * @brief Returns the last read value from STATUS_CML.
209      */
210     uint64_t getStatusCML() const
211     {
212         return statusCML;
213     }
214 
215     /**
216      * @brief Returns the last read value from STATUS_VOUT.
217      */
218     uint64_t getStatusVout() const
219     {
220         return statusVout;
221     }
222 
223     /**
224      * @brief Returns the last value read from STATUS_IOUT.
225      */
226     uint64_t getStatusIout() const
227     {
228         return statusIout;
229     }
230 
231     /**
232      * @brief Returns the last value read from STATUS_FANS_1_2.
233      */
234     uint64_t getStatusFans12() const
235     {
236         return statusFans12;
237     }
238 
239     /**
240      * @brief Returns the last value read from STATUS_TEMPERATURE.
241      */
242     uint64_t getStatusTemperature() const
243     {
244         return statusTemperature;
245     }
246 
247     /**
248      * @brief Returns true if a fault was found.
249      */
250     bool isFaulted() const
251     {
252         return (hasCommFault() || (vinUVFault >= DEGLITCH_LIMIT) ||
253                 (inputFault >= DEGLITCH_LIMIT) ||
254                 (voutOVFault >= DEGLITCH_LIMIT) ||
255                 (ioutOCFault >= DEGLITCH_LIMIT) ||
256                 (voutUVFault >= DEGLITCH_LIMIT) ||
257                 (fanFault >= DEGLITCH_LIMIT) || (tempFault >= DEGLITCH_LIMIT) ||
258                 (pgoodFault >= DEGLITCH_LIMIT) || (mfrFault >= DEGLITCH_LIMIT));
259     }
260 
261     /**
262      * @brief Return whether a fault has been logged for this power supply
263      */
264     bool isFaultLogged() const
265     {
266         return faultLogged;
267     }
268 
269     /**
270      * @brief Called when a fault for this power supply has been logged.
271      */
272     void setFaultLogged()
273     {
274         faultLogged = true;
275     }
276 
277     /**
278      * @brief Returns true if INPUT fault occurred.
279      */
280     bool hasInputFault() const
281     {
282         return (inputFault >= DEGLITCH_LIMIT);
283     }
284 
285     /**
286      * @brief Returns true if MFRSPECIFIC occurred.
287      */
288     bool hasMFRFault() const
289     {
290         return (mfrFault >= DEGLITCH_LIMIT);
291     }
292 
293     /**
294      * @brief Returns true if VIN_UV_FAULT occurred.
295      */
296     bool hasVINUVFault() const
297     {
298         return (vinUVFault >= DEGLITCH_LIMIT);
299     }
300 
301     /**
302      * @brief Returns true if VOUT_OV_FAULT occurred.
303      */
304     bool hasVoutOVFault() const
305     {
306         return (voutOVFault >= DEGLITCH_LIMIT);
307     }
308 
309     /**
310      * @brief Returns true if IOUT_OC fault occurred (bit 4 STATUS_BYTE).
311      */
312     bool hasIoutOCFault() const
313     {
314         return (ioutOCFault >= DEGLITCH_LIMIT);
315     }
316 
317     /**
318      * @brief Returns true if VOUT_UV_FAULT occurred.
319      */
320     bool hasVoutUVFault() const
321     {
322         return (voutUVFault >= DEGLITCH_LIMIT);
323     }
324 
325     /**
326      *@brief Returns true if fan fault occurred.
327      */
328     bool hasFanFault() const
329     {
330         return (fanFault >= DEGLITCH_LIMIT);
331     }
332 
333     /**
334      * @brief Returns true if TEMPERATURE fault occurred.
335      */
336     bool hasTempFault() const
337     {
338         return (tempFault >= DEGLITCH_LIMIT);
339     }
340 
341     /**
342      * @brief Returns true if there is a PGood fault (PGOOD# inactive, or OFF
343      * bit on).
344      */
345     bool hasPgoodFault() const
346     {
347         return (pgoodFault >= DEGLITCH_LIMIT);
348     }
349 
350     /**
351      * @brief Return true if there is a PS_Kill fault.
352      */
353     bool hasPSKillFault() const
354     {
355         return (psKillFault >= DEGLITCH_LIMIT);
356     }
357 
358     /**
359      * @brief Returns true if there is a 12Vcs (standy power) fault.
360      */
361     bool hasPS12VcsFault() const
362     {
363         return (ps12VcsFault >= DEGLITCH_LIMIT);
364     }
365 
366     /**
367      * @brief Returns true if there is a 12V current-share fault.
368      */
369     bool hasPSCS12VFault() const
370     {
371         return (psCS12VFault >= DEGLITCH_LIMIT);
372     }
373 
374     /**
375      * @brief Returns the device path
376      *
377      * This can be used for error call outs.
378      * Example: /sys/bus/i2c/devices/3-0068
379      */
380     const std::string getDevicePath() const
381     {
382         return pmbusIntf->path();
383     }
384 
385     /**
386      * @brief Returns this power supply's inventory path.
387      *
388      * This can be used for error call outs.
389      * Example:
390      * /xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply1
391      */
392     const std::string& getInventoryPath() const
393     {
394         return inventoryPath;
395     }
396 
397     /**
398      * @brief Returns the short name (last part of inventoryPath).
399      */
400     const std::string& getShortName() const
401     {
402         return shortName;
403     }
404 
405     /**
406      * @brief Returns the firmware revision version read from the power supply
407      */
408     const std::string& getFWVersion() const
409     {
410         return fwVersion;
411     }
412 
413     /**
414      * @brief Returns the model name of the power supply
415      */
416     const std::string& getModelName() const
417     {
418         return modelName;
419     }
420 
421     /** @brief Returns true if the number of failed reads exceeds limit
422      * TODO: or CML bit on.
423      */
424     bool hasCommFault() const
425     {
426         return ((readFail >= LOG_LIMIT) || (cmlFault >= DEGLITCH_LIMIT));
427     }
428 
429     /**
430      * @brief Reads the pmbus input voltage and returns that actual voltage
431      *        reading and the calculated input voltage based on thresholds.
432      * @param[out] actualInputVoltage - The actual voltage reading, in Volts.
433      * @param[out] inputVoltage - A rounded up/down value of the actual input
434      *             voltage based on thresholds, in Volts.
435      */
436     void getInputVoltage(double& actualInputVoltage, int& inputVoltage) const;
437 
438     /**
439      * @brief Check if the PS is considered to be available or not
440      *
441      * It is unavailable if any of:
442      * - not present
443      * - input fault active
444      * - Vin UV fault active
445      * - PS KILL fault active
446      * - Iout OC fault active
447      *
448      * Other faults will, through creating error logs with callouts, already
449      * be setting the Functional property to false.
450      *
451      * On changes, the Available property is updated in the inventory.
452      */
453     void checkAvailability();
454 
455     /**
456      * @brief Setup for power supply input history.
457      *
458      * This will setup the variables and interfaces needed to get the power
459      * supply input history data over to D-Bus. The only known support for this
460      * at this time is the INPUT_HISTORY command implemented by the IBM Common
461      * Form Factor Power Suppplies (ibm-cffps). The INPUT_HISTORY command for
462      * ibm-cffps is implemented via a manufacturing specific PMBus command.
463      */
464     void setupInputHistory();
465 
466     /**
467      * @brief Returns true if this power supply has input history (supported).
468      */
469     bool hasInputHistory() const
470     {
471         return inputHistorySupported;
472     }
473 
474     /**
475      * @brief Returns the number of input history records
476      *
477      * PowerSupply wrapper to getNumRecords() from RecordManager.
478      */
479     size_t getNumInputHistoryRecords() const
480     {
481         if (recordManager)
482         {
483             return recordManager->getNumRecords();
484         }
485         else
486         {
487             return 0;
488         }
489     }
490 
491   private:
492     /** @brief systemd bus member */
493     sdbusplus::bus::bus& bus;
494 
495     /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/
496     uint64_t statusWord = 0;
497 
498     /** @brief Will be set to the last read value of STATUS_WORD. */
499     uint64_t statusWordOld = 0;
500 
501     /** @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.*/
502     uint64_t statusInput = 0;
503 
504     /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/
505     uint64_t statusMFR = 0;
506 
507     /** @brief Will be updated to the latest/last value read from STATUS_CML.*/
508     uint64_t statusCML = 0;
509 
510     /** @brief Will be updated to the latest/last value read from STATUS_VOUT.*/
511     uint64_t statusVout = 0;
512 
513     /** @brief Will be updated to the latest/last value read from STATUS_IOUT.*/
514     uint64_t statusIout = 0;
515 
516     /** @brief Will be updated to the latest/last value read from
517      * STATUS_FANS_1_2. */
518     uint64_t statusFans12 = 0;
519 
520     /** @brief Will be updated to the latest/last value read from
521      * STATUS_TEMPERATURE.*/
522     uint64_t statusTemperature = 0;
523 
524     /** @brief Will be updated with latest converted value read from READ_VIN */
525     int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
526 
527     /** @brief Will be updated with the actual voltage last read from READ_VIN
528      */
529     double actualInputVoltage = 0;
530 
531     /** @brief True if an error for a fault has already been logged. */
532     bool faultLogged = false;
533 
534     /** @brief Incremented if bit 1 of STATUS_WORD low byte is on.
535      *
536      * Considered faulted if reaches DEGLITCH_LIMIT.
537      */
538     size_t cmlFault = 0;
539 
540     /** @brief Incremented if bit 5 of STATUS_WORD high byte is on.
541      *
542      * Considered faulted if reaches DEGLITCH_LIMIT.
543      */
544     size_t inputFault = 0;
545 
546     /** @brief Incremented if bit 4 of STATUS_WORD high byte is on.
547      *
548      * Considered faulted if reaches DEGLITCH_LIMIT.
549      */
550     size_t mfrFault = 0;
551 
552     /** @brief Incremented if bit 3 of STATUS_WORD low byte is on.
553      *
554      * Considered faulted if reaches DEGLITCH_LIMIT.
555      */
556     size_t vinUVFault = 0;
557 
558     /** @brief Incremented if bit 5 of STATUS_WORD low byte is on.
559      *
560      * Considered faulted if reaches DEGLITCH_LIMIT.
561      */
562     size_t voutOVFault = 0;
563 
564     /** @brief Incremented if bit 4 of STATUS_WORD low byte is on.
565      *
566      * Considered faulted if reaches DEGLITCH_LIMIT.
567      */
568     size_t ioutOCFault = 0;
569 
570     /** @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
571      * (VOUT_OV) of low byte is off.
572      *
573      * Considered faulted if reaches DEGLITCH_LIMIT.
574      */
575     size_t voutUVFault = 0;
576 
577     /** @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
578      *
579      * Considered faulted if reaches DEGLITCH_LIMIT.
580      */
581     size_t fanFault = 0;
582 
583     /** @brief Incremented if bit 2 of STATUS_WORD low byte is on.
584      *
585      * Considered faulted if reaches DEGLITCH_LIMIT. */
586     size_t tempFault = 0;
587 
588     /**
589      * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
590      * inactive, or the unit is off.
591      *
592      * Considered faulted if reaches DEGLITCH_LIMIT.
593      */
594     size_t pgoodFault = 0;
595 
596     /**
597      * @brief Power Supply Kill fault.
598      *
599      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
600      * bit 4 to indicate this fault. Considered faulted if it reaches
601      * DEGLITCH_LIMIT.
602      */
603     size_t psKillFault = 0;
604 
605     /**
606      * @brief Power Supply 12Vcs fault (standby power).
607      *
608      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
609      * bit 6 to indicate this fault. Considered faulted if it reaches
610      * DEGLITCH_LIMIT.
611      */
612     size_t ps12VcsFault = 0;
613 
614     /**
615      * @brief Power Supply Current-Share fault in 12V domain.
616      *
617      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
618      * bit 7 to indicate this fault. Considered faulted if it reaches
619      * DEGLITCH_LIMIT.
620      */
621     size_t psCS12VFault = 0;
622 
623     /** @brief Count of the number of read failures. */
624     size_t readFail = 0;
625 
626     /**
627      * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
628      */
629     void analyzeCMLFault();
630 
631     /**
632      * @brief Examine STATUS_WORD for INPUT bit on.
633      *
634      * "An input voltage, input current, or input power fault or warning has
635      * occurred."
636      */
637     void analyzeInputFault();
638 
639     /**
640      * @brief Examine STATUS_WORD for VOUT being set.
641      *
642      * If VOUT is on, "An output voltage fault or warning has occurred.", and
643      * VOUT_OV_FAULT is on, there is an output over-voltage fault.
644      */
645     void analyzeVoutOVFault();
646 
647     /*
648      * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
649      *
650      * "An output overcurrent fault has occurred." If it is on, and fault not
651      * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
652      */
653     void analyzeIoutOCFault();
654 
655     /**
656      * @brief Examines STATUS_WORD value read to see if there is a UV fault.
657      *
658      * Checks if the VOUT bit is on, indicating "An output voltage fault or
659      * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
660      * determined to be an indication of an output under-voltage fault.
661      */
662     void analyzeVoutUVFault();
663 
664     /**
665      * @brief Examine STATUS_WORD for the fan fault/warning bit.
666      *
667      * If fanFault is not on, trace that the bit now came on, include
668      * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
669      * help with understanding what may have caused it to be set.
670      */
671     void analyzeFanFault();
672 
673     /**
674      * @brief Examine STATUS_WORD for temperature fault.
675      */
676     void analyzeTemperatureFault();
677 
678     /**
679      * @brief Examine STATUS_WORD for pgood or unit off faults.
680      */
681     void analyzePgoodFault();
682 
683     /**
684      * @brief Determine possible manufacturer-specific faults from bits in
685      * STATUS_MFR.
686      *
687      * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
688      * Defined" meanings. Determine which faults, if any, are present based on
689      * the power supply (device driver) type.
690      */
691     void determineMFRFault();
692 
693     /**
694      * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
695      *
696      * "A manufacturer specific fault or warning has occurred."
697      *
698      * If it is on, call the determineMFRFault() helper function to examine the
699      * value read from STATUS_MFR_SPECIFIC.
700      */
701     void analyzeMFRFault();
702 
703     /**
704      * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
705      */
706     void analyzeVinUVFault();
707 
708     /**
709      * @brief D-Bus path to use for this power supply's inventory status.
710      **/
711     std::string inventoryPath;
712 
713     /**
714      * @brief Store the short name to avoid string processing.
715      *
716      * The short name will be something like powersupply1, the last part of the
717      * inventoryPath.
718      */
719     std::string shortName;
720 
721     /**
722      * @brief Given a full inventory path, returns the last node of the path as
723      * the "short name"
724      */
725     std::string findShortName(const std::string& invPath)
726     {
727         auto const lastSlashPos = invPath.find_last_of('/');
728 
729         if ((lastSlashPos == std::string::npos) ||
730             ((lastSlashPos + 1) == invPath.size()))
731         {
732             return invPath;
733         }
734         else
735         {
736             return invPath.substr(lastSlashPos + 1);
737         }
738     }
739 
740     /**
741      * @brief The libgpiod object for monitoring PSU presence
742      */
743     std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
744 
745     /** @brief True if the power supply is present. */
746     bool present = false;
747 
748     /** @brief Power supply model name. */
749     std::string modelName;
750 
751     /** @brief D-Bus match variable used to subscribe to Present property
752      * changes.
753      **/
754     std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
755 
756     /** @brief D-Bus match variable used to subscribe for Present property
757      * interface added.
758      */
759     std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
760 
761     /**
762      * @brief Pointer to the PMBus interface
763      *
764      * Used to read or write to/from PMBus power supply devices.
765      */
766     std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
767 
768     /** @brief Stored copy of the firmware version/revision string */
769     std::string fwVersion;
770 
771     /**
772      * @brief The file system path used for binding the device driver.
773      */
774     const std::filesystem::path bindPath;
775 
776     /* @brief The string to pass in for binding the device driver. */
777     std::string bindDevice;
778 
779     /**
780      * @brief The result of the most recent availability check
781      *
782      * Saved on the object so changes can be detected.
783      */
784     bool available = false;
785 
786     /**
787      * @brief Binds or unbinds the power supply device driver
788      *
789      * Called when a presence change is detected to either bind the device
790      * driver for the power supply when it is installed, or unbind the device
791      * driver when the power supply is removed.
792      *
793      * Writes <device> to <path>/bind (or unbind)
794      *
795      * @param present - when true, will bind the device driver
796      *                  when false, will unbind the device driver
797      */
798     void bindOrUnbindDriver(bool present);
799 
800     /**
801      *  @brief Updates the presence status by querying D-Bus
802      *
803      * The D-Bus inventory properties for this power supply will be read to
804      * determine if the power supply is present or not and update this
805      * object's present member variable to reflect current status.
806      **/
807     void updatePresence();
808 
809     /**
810      * @brief Updates the power supply presence by reading the GPIO line.
811      */
812     void updatePresenceGPIO();
813 
814     /**
815      * @brief Callback for inventory property changes
816      *
817      * Process change of Present property for power supply.
818      *
819      * This is used if we are watching the D-Bus properties instead of reading
820      * the GPIO presence line ourselves.
821      *
822      * @param[in]  msg - Data associated with Present change signal
823      **/
824     void inventoryChanged(sdbusplus::message::message& msg);
825 
826     /**
827      * @brief Callback for inventory property added.
828      *
829      * Process add of the interface with the Present property for power supply.
830      *
831      * This is used if we are watching the D-Bus properties instead of reading
832      * the GPIO presence line ourselves.
833      *
834      * @param[in]  msg - Data associated with Present add signal
835      **/
836     void inventoryAdded(sdbusplus::message::message& msg);
837 
838     /**
839      * @brief Reads the most recent input history record from the power supply
840      * and updates the average and maximum properties in D-Bus if there is a new
841      * reading available.
842      *
843      * This will still run every time analyze() is called so code can post new
844      * data as soon as possible and the timestamp will more accurately reflect
845      * the correct time.
846      *
847      * D-Bus is only updated if there is a change and the oldest record will be
848      * pruned if the property already contains the max number of records.
849      */
850     void updateHistory();
851 
852     /**
853      * @brief Set to true if INPUT_HISTORY command supported.
854      *
855      * Not all power supplies will support the INPUT_HISTORY command. The IBM
856      * Common Form Factor power supplies do support this command.
857      */
858     bool inputHistorySupported{false};
859 
860     /**
861      * @brief Class that manages the input power history records.
862      **/
863     std::unique_ptr<history::RecordManager> recordManager;
864 
865     /**
866      * @brief The D-Bus object for the average input power history
867      **/
868     std::unique_ptr<history::Average> average;
869 
870     /**
871      * @brief The D-Bus object for the maximum input power history
872      **/
873     std::unique_ptr<history::Maximum> maximum;
874 
875     /**
876      * @brief The base D-Bus object path to use for the average and maximum
877      * objects.
878      **/
879     std::string historyObjectPath;
880 };
881 
882 } // namespace phosphor::power::psu
883