1 #pragma once
2 
3 #include "manager.hpp"
4 #include "property_change_listener.hpp"
5 
6 #include <sdbusplus/bus.hpp>
7 #include <xyz/openbmc_project/Time/EpochTime/server.hpp>
8 
9 #include <chrono>
10 
11 namespace phosphor
12 {
13 namespace time
14 {
15 
16 using namespace std::chrono;
17 
18 using EpochTimeIntf = sdbusplus::server::object_t<
19     sdbusplus::xyz::openbmc_project::Time::server::EpochTime>;
20 
21 /** @class BmcEpoch
22  *  @brief OpenBMC BMC EpochTime implementation.
23  *  @details A concrete implementation for
24  * xyz.openbmc_project.Time.EpochTime DBus API for BMC's epoch time.
25  */
26 class BmcEpoch : public EpochTimeIntf, public PropertyChangeListner
27 {
28   public:
29     BmcEpoch(sdbusplus::bus_t& bus, const char* objPath, Manager& manager) :
30         EpochTimeIntf(bus, objPath), bus(bus), manager(manager)
31     {
32         initialize();
33     }
34 
35     ~BmcEpoch() override;
36 
37     BmcEpoch(const BmcEpoch&) = delete;
38     BmcEpoch(BmcEpoch&&) = delete;
39     BmcEpoch& operator=(const BmcEpoch&) = delete;
40     BmcEpoch& operator=(BmcEpoch&&) = delete;
41 
42     /** @brief Notified on time mode changed */
43     void onModeChanged(Mode mode) override;
44 
45     /**
46      * @brief Get value of Elapsed property
47      *
48      * @return The elapsed microseconds since UTC
49      **/
50     uint64_t elapsed() const override;
51 
52     /**
53      * @brief Set value of Elapsed property
54      *
55      * @param[in] value - The microseconds since UTC to set
56      * @return The updated elapsed microseconds since UTC
57      **/
58     uint64_t elapsed(uint64_t value) override;
59 
60   protected:
61     /** @brief Persistent sdbusplus DBus connection */
62     sdbusplus::bus_t& bus;
63 
64     /** @brief The manager to handle OpenBMC time */
65     Manager& manager;
66 
67     /** @brief Set current time to system
68      *
69      * This function set the time to system by invoking systemd
70      * org.freedesktop.timedate1's SetTime method.
71      *
72      * @param[in] timeOfDayUsec - Microseconds since UTC
73      *
74      * @return true or false to indicate if it sets time successfully
75      */
76     bool setTime(const std::chrono::microseconds& timeOfDayUsec);
77 
78     /** @brief Get current time
79      *
80      * @return Microseconds since UTC
81      */
82     static std::chrono::microseconds getTime();
83 
84   private:
85     /** @brief The fd for time change event */
86     int timeFd = -1;
87 
88     /** @brief Initialize timerFd related resource */
89     void initialize();
90 
91     /** @brief The callback function on system time change
92      *
93      * @param[in] es - Source of the event
94      * @param[in] fd - File descriptor of the timer
95      * @param[in] revents - Not used
96      * @param[in] userdata - User data pointer
97      */
98     static int onTimeChange(sd_event_source* es, int fd, uint32_t revents,
99                             void* userdata);
100 
101     /** @brief The deleter of sd_event_source */
102     std::function<void(sd_event_source*)> sdEventSourceDeleter =
103         [](sd_event_source* p) {
104         if (p)
105         {
106             sd_event_source_unref(p);
107         }
108     };
109     using SdEventSource =
110         std::unique_ptr<sd_event_source, decltype(sdEventSourceDeleter)>;
111 
112     /** @brief The event source on system time change */
113     SdEventSource timeChangeEventSource{nullptr, sdEventSourceDeleter};
114 };
115 
116 } // namespace time
117 } // namespace phosphor
118