xref: /DragonOS/kernel/src/driver/rtc/mod.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
1 use core::fmt::Debug;
2 
3 use alloc::{string::String, sync::Arc};
4 use system_error::SystemError;
5 
6 use crate::{
7     libs::rwlock::RwLock,
8     time::{Instant, PosixTimeSpec, NSEC_PER_SEC},
9 };
10 
11 use self::sysfs::RtcGeneralDevice;
12 
13 use super::base::device::Device;
14 
15 pub mod class;
16 pub mod interface;
17 pub mod rtc_cmos;
18 mod sysfs;
19 mod utils;
20 
21 /// 全局默认rtc
22 static GLOBAL_DEFAULT_RTC: RwLock<Option<Arc<RtcGeneralDevice>>> = RwLock::new(None);
23 
24 /// 获取全局的默认的rtc
25 fn global_default_rtc() -> Option<Arc<RtcGeneralDevice>> {
26     GLOBAL_DEFAULT_RTC.read().clone()
27 }
28 
29 /// 注册默认的rtc
30 fn register_default_rtc(general_device: Arc<RtcGeneralDevice>) -> bool {
31     let upg = GLOBAL_DEFAULT_RTC.upgradeable_read();
32     if let Some(old_dev) = upg.as_ref() {
33         if old_dev.priority() >= general_device.priority() {
34             return false;
35         }
36     }
37 
38     let mut write = upg.upgrade();
39 
40     write.replace(general_device);
41 
42     return true;
43 }
44 
45 /// RTC设备的trait
46 pub trait RtcDevice: Device {
47     fn class_ops(&self) -> &'static dyn RtcClassOps;
48 }
49 
50 pub trait RtcClassOps: Send + Sync + Debug {
51     fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>;
52     fn set_time(&self, dev: &Arc<dyn RtcDevice>, time: &RtcTime) -> Result<(), SystemError>;
53 }
54 
55 #[derive(Default, Debug, Clone, Copy)]
56 pub struct RtcTime {
57     /// `second`: 秒,范围从 0 到 59
58     pub second: i32,
59     /// `minute`: 分钟,范围从 0 到 59
60     pub minute: i32,
61     /// `hour`: 小时,范围从 0 到 23
62     pub hour: i32,
63     /// `mday`: 一个月中的第几天,范围从 1 到 31
64     pub mday: i32,
65     /// `month`: 月份,范围从 0 到 11
66     pub month: i32,
67     /// `year`: 年份(相对于1900年)
68     pub year: i32,
69     /// `wday`: 一周中的第几天,范围从 0(周日)到 6(周六)
70     pub wday: i32,
71     /// `yday`: 一年中的第几天,范围从 1 到 366
72     pub yday: i32,
73     /// `isdst`: 表示是否为夏令时,通常如果是夏令时,此值为正,否则为零或负
74     pub isdst: i32,
75 }
76 
77 impl RtcTime {
78     /// 返回一个格式化的日期字符串
79     ///
80     /// 例如,如果日期为2021年1月1日,则返回"2021-01-01"
81     pub fn date_string(&self) -> String {
82         format!(
83             "{:04}-{:02}-{:02}",
84             self.year_real(),
85             self.month_real(),
86             self.mday
87         )
88     }
89 
90     /// 返回一个格式化的时间字符串
91     ///
92     /// 例如,如果时间为12:00:00,则返回"12:00:00"
93     pub fn time_string(&self) -> String {
94         format!("{:02}:{:02}:{:02}", self.hour, self.minute, self.second)
95     }
96 
97     pub fn valid(&self) -> bool {
98         !(self.year < 70
99             || self.year > (i32::MAX - 1900)
100             || self.month >= 12
101             || self.month < 0
102             || self.mday < 1
103             || self.mday > self.month_days()
104             || self.hour >= 24
105             || self.hour < 0
106             || self.minute >= 60
107             || self.minute < 0
108             || self.second >= 60
109             || self.second < 0)
110     }
111 
112     /// 获取当月有多少天
113     pub fn month_days(&self) -> i32 {
114         let days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
115         let month = self.month as usize;
116         let mut days = days_in_month[month];
117 
118         if month == 1 && self.is_leap_year() {
119             days += 1;
120         }
121 
122         days
123     }
124 
125     /// 判断当前是否为闰年
126     pub fn is_leap_year(&self) -> bool {
127         let year = self.year + 1900;
128         (year % 4 == 0 && year % 100 != 0) || year % 400 == 0
129     }
130 
131     pub fn year_real(&self) -> i32 {
132         self.year + 1900
133     }
134 
135     pub fn month_real(&self) -> i32 {
136         self.month + 1
137     }
138 }
139 
140 impl From<RtcTime> for PosixTimeSpec {
141     fn from(val: RtcTime) -> Self {
142         let instant = Instant::mktime64(
143             val.year_real() as u32,
144             (val.month + 1) as u32,
145             (val.mday) as u32,
146             val.hour as u32,
147             val.minute as u32,
148             val.second as u32,
149         );
150 
151         /* 注意:RTC 仅存储完整的秒数。它是任意的,它存储的是最接近的值还是
152          * 分割秒数截断的值。然而,重要的是我们使用它来存储截断的值。这是因为
153          * 否则在 RTC 同步函数中,需要读取 both xtime.tv_sec 和 xtime.tv_nsec。
154          * 在某些处理器上(例如 ARM),对 >32位的原子读取是不可行的。所以,
155          * 存储最接近的值会减慢同步 API 的速度。因此,这里我们存储截断的值
156          * 并在后面加上 0.5s 的最佳猜测。
157          */
158         PosixTimeSpec::new(instant.secs(), (NSEC_PER_SEC >> 1).into())
159     }
160 }
161 
162 /// 全局默认rtc的优先级
163 #[allow(dead_code)]
164 #[derive(Debug, Default, PartialEq, PartialOrd, Clone, Copy)]
165 pub enum GeneralRtcPriority {
166     #[default]
167     L0 = 0,
168     L1,
169 }
170