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