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