cadmus_core/
rtc.rs

1use anyhow::Error;
2use chrono::{Datelike, Duration, Timelike, Utc};
3use nix::{ioctl_none, ioctl_read, ioctl_write_ptr};
4use std::fs::File;
5use std::mem;
6use std::os::unix::io::AsRawFd;
7use std::path::Path;
8
9ioctl_read!(rtc_read_alarm, b'p', 0x10, RtcWkalrm);
10ioctl_write_ptr!(rtc_write_alarm, b'p', 0x0f, RtcWkalrm);
11ioctl_none!(rtc_disable_alarm, b'p', 0x02);
12
13#[repr(C)]
14#[derive(Debug, Clone)]
15pub struct RtcTime {
16    tm_sec: libc::c_int,
17    tm_min: libc::c_int,
18    tm_hour: libc::c_int,
19    tm_mday: libc::c_int,
20    tm_mon: libc::c_int,
21    tm_year: libc::c_int,
22    tm_wday: libc::c_int,
23    tm_yday: libc::c_int,
24    tm_isdst: libc::c_int,
25}
26
27impl Default for RtcWkalrm {
28    fn default() -> Self {
29        unsafe { mem::zeroed() }
30    }
31}
32
33#[repr(C)]
34#[derive(Debug, Clone)]
35pub struct RtcWkalrm {
36    enabled: libc::c_uchar,
37    pending: libc::c_uchar,
38    time: RtcTime,
39}
40
41impl RtcTime {
42    fn year(&self) -> i32 {
43        1900 + self.tm_year as i32
44    }
45}
46
47impl RtcWkalrm {
48    pub fn enabled(&self) -> bool {
49        self.enabled == 1
50    }
51
52    pub fn year(&self) -> i32 {
53        self.time.year()
54    }
55}
56
57pub struct Rtc(File);
58
59impl Rtc {
60    pub fn new<P: AsRef<Path>>(path: P) -> Result<Rtc, Error> {
61        let file = File::open(path)?;
62        Ok(Rtc(file))
63    }
64
65    pub fn alarm(&self) -> Result<RtcWkalrm, Error> {
66        let mut rwa = RtcWkalrm::default();
67        unsafe {
68            rtc_read_alarm(self.0.as_raw_fd(), &mut rwa)
69                .map(|_| rwa)
70                .map_err(|e| e.into())
71        }
72    }
73
74    pub fn set_alarm(&self, days: f32) -> Result<i32, Error> {
75        let wt = Utc::now() + Duration::seconds((86_400.0 * days) as i64);
76        let rwa = RtcWkalrm {
77            enabled: 1,
78            pending: 0,
79            time: RtcTime {
80                tm_sec: wt.second() as libc::c_int,
81                tm_min: wt.minute() as libc::c_int,
82                tm_hour: wt.hour() as libc::c_int,
83                tm_mday: wt.day() as libc::c_int,
84                tm_mon: wt.month0() as libc::c_int,
85                tm_year: (wt.year() - 1900) as libc::c_int,
86                tm_wday: -1,
87                tm_yday: -1,
88                tm_isdst: -1,
89            },
90        };
91        unsafe { rtc_write_alarm(self.0.as_raw_fd(), &rwa).map_err(|e| e.into()) }
92    }
93
94    pub fn disable_alarm(&self) -> Result<i32, Error> {
95        unsafe { rtc_disable_alarm(self.0.as_raw_fd()).map_err(|e| e.into()) }
96    }
97}