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
global_default_rtc() -> Option<Arc<RtcGeneralDevice>>25 fn global_default_rtc() -> Option<Arc<RtcGeneralDevice>> {
26 GLOBAL_DEFAULT_RTC.read().clone()
27 }
28
29 /// 注册默认的rtc
register_default_rtc(general_device: Arc<RtcGeneralDevice>) -> bool30 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 {
class_ops(&self) -> &'static dyn RtcClassOps47 fn class_ops(&self) -> &'static dyn RtcClassOps;
48 }
49
50 #[allow(dead_code)]
51 pub trait RtcClassOps: Send + Sync + Debug {
read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>52 fn read_time(&self, dev: &Arc<dyn RtcDevice>) -> Result<RtcTime, SystemError>;
set_time(&self, dev: &Arc<dyn RtcDevice>, time: &RtcTime) -> Result<(), 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"
date_string(&self) -> String82 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"
time_string(&self) -> String94 pub fn time_string(&self) -> String {
95 format!("{:02}:{:02}:{:02}", self.hour, self.minute, self.second)
96 }
97
valid(&self) -> bool98 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 /// 获取当月有多少天
month_days(&self) -> i32114 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 /// 判断当前是否为闰年
is_leap_year(&self) -> bool127 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
year_real(&self) -> i32132 pub fn year_real(&self) -> i32 {
133 self.year + 1900
134 }
135
month_real(&self) -> i32136 pub fn month_real(&self) -> i32 {
137 self.month + 1
138 }
139 }
140
141 impl From<RtcTime> for PosixTimeSpec {
from(val: RtcTime) -> Self142 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