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     /**
492      * @brief Returns true when INPUT_HISTORY sync is required.
493      */
494     bool isSyncHistoryRequired() const
495     {
496         return syncHistoryRequired;
497     }
498 
499     /**
500      * @brief Clears the indicator that sync required for INPUT_HISTORY.
501      *
502      * Sets variable to false to indicate that the sync is no longer required.
503      * This can be used after the PSUManager has reacted to the need for the
504      * INPUT_HISTORY data to be synchronized.
505      */
506     void clearSyncHistoryRequired()
507     {
508         syncHistoryRequired = false;
509     }
510 
511   private:
512     /** @brief systemd bus member */
513     sdbusplus::bus::bus& bus;
514 
515     /** @brief Will be updated to the latest/lastvalue read from STATUS_WORD.*/
516     uint64_t statusWord = 0;
517 
518     /** @brief Will be set to the last read value of STATUS_WORD. */
519     uint64_t statusWordOld = 0;
520 
521     /** @brief Will be updated to the latest/lastvalue read from STATUS_INPUT.*/
522     uint64_t statusInput = 0;
523 
524     /** @brief Will be updated to the latest/lastvalue read from STATUS_MFR.*/
525     uint64_t statusMFR = 0;
526 
527     /** @brief Will be updated to the latest/last value read from STATUS_CML.*/
528     uint64_t statusCML = 0;
529 
530     /** @brief Will be updated to the latest/last value read from STATUS_VOUT.*/
531     uint64_t statusVout = 0;
532 
533     /** @brief Will be updated to the latest/last value read from STATUS_IOUT.*/
534     uint64_t statusIout = 0;
535 
536     /** @brief Will be updated to the latest/last value read from
537      * STATUS_FANS_1_2. */
538     uint64_t statusFans12 = 0;
539 
540     /** @brief Will be updated to the latest/last value read from
541      * STATUS_TEMPERATURE.*/
542     uint64_t statusTemperature = 0;
543 
544     /** @brief Will be updated with latest converted value read from READ_VIN */
545     int inputVoltage = phosphor::pmbus::in_input::VIN_VOLTAGE_0;
546 
547     /** @brief Will be updated with the actual voltage last read from READ_VIN
548      */
549     double actualInputVoltage = 0;
550 
551     /** @brief True if an error for a fault has already been logged. */
552     bool faultLogged = false;
553 
554     /** @brief Incremented if bit 1 of STATUS_WORD low byte is on.
555      *
556      * Considered faulted if reaches DEGLITCH_LIMIT.
557      */
558     size_t cmlFault = 0;
559 
560     /** @brief Incremented if bit 5 of STATUS_WORD high byte is on.
561      *
562      * Considered faulted if reaches DEGLITCH_LIMIT.
563      */
564     size_t inputFault = 0;
565 
566     /** @brief Incremented if bit 4 of STATUS_WORD high byte is on.
567      *
568      * Considered faulted if reaches DEGLITCH_LIMIT.
569      */
570     size_t mfrFault = 0;
571 
572     /** @brief Incremented if bit 3 of STATUS_WORD low byte is on.
573      *
574      * Considered faulted if reaches DEGLITCH_LIMIT.
575      */
576     size_t vinUVFault = 0;
577 
578     /** @brief Incremented if bit 5 of STATUS_WORD low byte is on.
579      *
580      * Considered faulted if reaches DEGLITCH_LIMIT.
581      */
582     size_t voutOVFault = 0;
583 
584     /** @brief Incremented if bit 4 of STATUS_WORD low byte is on.
585      *
586      * Considered faulted if reaches DEGLITCH_LIMIT.
587      */
588     size_t ioutOCFault = 0;
589 
590     /** @brief Incremented if bit 7 of STATUS_WORD high byte is on and bit 5
591      * (VOUT_OV) of low byte is off.
592      *
593      * Considered faulted if reaches DEGLITCH_LIMIT.
594      */
595     size_t voutUVFault = 0;
596 
597     /** @brief Incremented if FANS fault/warn bit on in STATUS_WORD.
598      *
599      * Considered faulted if reaches DEGLITCH_LIMIT.
600      */
601     size_t fanFault = 0;
602 
603     /** @brief Incremented if bit 2 of STATUS_WORD low byte is on.
604      *
605      * Considered faulted if reaches DEGLITCH_LIMIT. */
606     size_t tempFault = 0;
607 
608     /**
609      * @brief Incremented if bit 11 or 6 of STATUS_WORD is on. PGOOD# is
610      * inactive, or the unit is off.
611      *
612      * Considered faulted if reaches DEGLITCH_LIMIT.
613      */
614     size_t pgoodFault = 0;
615 
616     /**
617      * @brief Power Supply Kill fault.
618      *
619      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
620      * bit 4 to indicate this fault. Considered faulted if it reaches
621      * DEGLITCH_LIMIT.
622      */
623     size_t psKillFault = 0;
624 
625     /**
626      * @brief Power Supply 12Vcs fault (standby power).
627      *
628      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
629      * bit 6 to indicate this fault. Considered faulted if it reaches
630      * DEGLITCH_LIMIT.
631      */
632     size_t ps12VcsFault = 0;
633 
634     /**
635      * @brief Power Supply Current-Share fault in 12V domain.
636      *
637      * Incremented based on bits in STATUS_MFR_SPECIFIC. IBM power supplies use
638      * bit 7 to indicate this fault. Considered faulted if it reaches
639      * DEGLITCH_LIMIT.
640      */
641     size_t psCS12VFault = 0;
642 
643     /** @brief Count of the number of read failures. */
644     size_t readFail = 0;
645 
646     /**
647      * @brief Examine STATUS_WORD for CML (communication, memory, logic fault).
648      */
649     void analyzeCMLFault();
650 
651     /**
652      * @brief Examine STATUS_WORD for INPUT bit on.
653      *
654      * "An input voltage, input current, or input power fault or warning has
655      * occurred."
656      */
657     void analyzeInputFault();
658 
659     /**
660      * @brief Examine STATUS_WORD for VOUT being set.
661      *
662      * If VOUT is on, "An output voltage fault or warning has occurred.", and
663      * VOUT_OV_FAULT is on, there is an output over-voltage fault.
664      */
665     void analyzeVoutOVFault();
666 
667     /*
668      * @brief Examine STATUS_WORD value read for IOUT_OC_FAULT.
669      *
670      * "An output overcurrent fault has occurred." If it is on, and fault not
671      * set, trace STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_IOUT values.
672      */
673     void analyzeIoutOCFault();
674 
675     /**
676      * @brief Examines STATUS_WORD value read to see if there is a UV fault.
677      *
678      * Checks if the VOUT bit is on, indicating "An output voltage fault or
679      * warning has occurred", if it is on, but VOUT_OV_FAULT is off, it is
680      * determined to be an indication of an output under-voltage fault.
681      */
682     void analyzeVoutUVFault();
683 
684     /**
685      * @brief Examine STATUS_WORD for the fan fault/warning bit.
686      *
687      * If fanFault is not on, trace that the bit now came on, include
688      * STATUS_WORD, STATUS_MFR_SPECIFIC, and STATUS_FANS_1_2 values as well, to
689      * help with understanding what may have caused it to be set.
690      */
691     void analyzeFanFault();
692 
693     /**
694      * @brief Examine STATUS_WORD for temperature fault.
695      */
696     void analyzeTemperatureFault();
697 
698     /**
699      * @brief Examine STATUS_WORD for pgood or unit off faults.
700      */
701     void analyzePgoodFault();
702 
703     /**
704      * @brief Determine possible manufacturer-specific faults from bits in
705      * STATUS_MFR.
706      *
707      * The bits in the STATUS_MFR_SPECIFIC command response have "Manufacturer
708      * Defined" meanings. Determine which faults, if any, are present based on
709      * the power supply (device driver) type.
710      */
711     void determineMFRFault();
712 
713     /**
714      * @brief Examine STATUS_WORD value read for MFRSPECIFIC bit on.
715      *
716      * "A manufacturer specific fault or warning has occurred."
717      *
718      * If it is on, call the determineMFRFault() helper function to examine the
719      * value read from STATUS_MFR_SPECIFIC.
720      */
721     void analyzeMFRFault();
722 
723     /**
724      * @brief Analyzes the STATUS_WORD for a VIN_UV_FAULT indicator.
725      */
726     void analyzeVinUVFault();
727 
728     /**
729      * @brief D-Bus path to use for this power supply's inventory status.
730      **/
731     std::string inventoryPath;
732 
733     /**
734      * @brief Store the short name to avoid string processing.
735      *
736      * The short name will be something like powersupply1, the last part of the
737      * inventoryPath.
738      */
739     std::string shortName;
740 
741     /**
742      * @brief Given a full inventory path, returns the last node of the path as
743      * the "short name"
744      */
745     std::string findShortName(const std::string& invPath)
746     {
747         auto const lastSlashPos = invPath.find_last_of('/');
748 
749         if ((lastSlashPos == std::string::npos) ||
750             ((lastSlashPos + 1) == invPath.size()))
751         {
752             return invPath;
753         }
754         else
755         {
756             return invPath.substr(lastSlashPos + 1);
757         }
758     }
759 
760     /**
761      * @brief The libgpiod object for monitoring PSU presence
762      */
763     std::unique_ptr<GPIOInterfaceBase> presenceGPIO = nullptr;
764 
765     /** @brief True if the power supply is present. */
766     bool present = false;
767 
768     /** @brief Power supply model name. */
769     std::string modelName;
770 
771     /** @brief D-Bus match variable used to subscribe to Present property
772      * changes.
773      **/
774     std::unique_ptr<sdbusplus::bus::match_t> presentMatch;
775 
776     /** @brief D-Bus match variable used to subscribe for Present property
777      * interface added.
778      */
779     std::unique_ptr<sdbusplus::bus::match_t> presentAddedMatch;
780 
781     /**
782      * @brief Pointer to the PMBus interface
783      *
784      * Used to read or write to/from PMBus power supply devices.
785      */
786     std::unique_ptr<phosphor::pmbus::PMBusBase> pmbusIntf = nullptr;
787 
788     /** @brief Stored copy of the firmware version/revision string */
789     std::string fwVersion;
790 
791     /**
792      * @brief The file system path used for binding the device driver.
793      */
794     const std::filesystem::path bindPath;
795 
796     /* @brief The string to pass in for binding the device driver. */
797     std::string bindDevice;
798 
799     /**
800      * @brief The result of the most recent availability check
801      *
802      * Saved on the object so changes can be detected.
803      */
804     bool available = false;
805 
806     /**
807      * @brief Binds or unbinds the power supply device driver
808      *
809      * Called when a presence change is detected to either bind the device
810      * driver for the power supply when it is installed, or unbind the device
811      * driver when the power supply is removed.
812      *
813      * Writes <device> to <path>/bind (or unbind)
814      *
815      * @param present - when true, will bind the device driver
816      *                  when false, will unbind the device driver
817      */
818     void bindOrUnbindDriver(bool present);
819 
820     /**
821      *  @brief Updates the presence status by querying D-Bus
822      *
823      * The D-Bus inventory properties for this power supply will be read to
824      * determine if the power supply is present or not and update this
825      * object's present member variable to reflect current status.
826      **/
827     void updatePresence();
828 
829     /**
830      * @brief Updates the power supply presence by reading the GPIO line.
831      */
832     void updatePresenceGPIO();
833 
834     /**
835      * @brief Callback for inventory property changes
836      *
837      * Process change of Present property for power supply.
838      *
839      * This is used if we are watching the D-Bus properties instead of reading
840      * the GPIO presence line ourselves.
841      *
842      * @param[in]  msg - Data associated with Present change signal
843      **/
844     void inventoryChanged(sdbusplus::message::message& msg);
845 
846     /**
847      * @brief Callback for inventory property added.
848      *
849      * Process add of the interface with the Present property for power supply.
850      *
851      * This is used if we are watching the D-Bus properties instead of reading
852      * the GPIO presence line ourselves.
853      *
854      * @param[in]  msg - Data associated with Present add signal
855      **/
856     void inventoryAdded(sdbusplus::message::message& msg);
857 
858     /**
859      * @brief Reads the most recent input history record from the power supply
860      * and updates the average and maximum properties in D-Bus if there is a new
861      * reading available.
862      *
863      * This will still run every time analyze() is called so code can post new
864      * data as soon as possible and the timestamp will more accurately reflect
865      * the correct time.
866      *
867      * D-Bus is only updated if there is a change and the oldest record will be
868      * pruned if the property already contains the max number of records.
869      */
870     void updateHistory();
871 
872     /**
873      * @brief Set to true if INPUT_HISTORY command supported.
874      *
875      * Not all power supplies will support the INPUT_HISTORY command. The IBM
876      * Common Form Factor power supplies do support this command.
877      */
878     bool inputHistorySupported{false};
879 
880     /**
881      * @brief Set to true when INPUT_HISTORY sync is required.
882      *
883      * A power supply will need to synchronize its INPUT_HISTORY data with the
884      * other power supplies installed in the system when it goes from missing to
885      * present.
886      */
887     bool syncHistoryRequired{false};
888 
889     /**
890      * @brief Class that manages the input power history records.
891      **/
892     std::unique_ptr<history::RecordManager> recordManager;
893 
894     /**
895      * @brief The D-Bus object for the average input power history
896      **/
897     std::unique_ptr<history::Average> average;
898 
899     /**
900      * @brief The D-Bus object for the maximum input power history
901      **/
902     std::unique_ptr<history::Maximum> maximum;
903 
904     /**
905      * @brief The base D-Bus object path to use for the average and maximum
906      * objects.
907      **/
908     std::string historyObjectPath;
909 };
910 
911 } // namespace phosphor::power::psu
912