extern crate chrono;
extern crate libc;
#[macro_use]
extern crate nix;
use chrono::{Datelike, Timelike};
use libc::c_int;
use std::{fs, io, path};
use std::os::unix::io::AsRawFd;
pub const YEAR_EPOCH: i32 = 1900;
mod ffi {
use super::RtcTime;
ioctl!(read rtc_rd_time with 'p', 0x09; RtcTime);
ioctl!(write_ptr rtc_set_time with 'p', 0x0a; RtcTime);
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
pub struct RtcTime {
pub tm_sec: c_int,
pub tm_min: c_int,
pub tm_hour: c_int,
pub tm_mday: c_int,
pub tm_mon: c_int,
pub tm_year: c_int,
pub tm_wday: c_int,
pub tm_yday: c_int,
pub tm_isdst: c_int,
}
impl From<RtcTime> for chrono::NaiveDateTime {
fn from(rtc: RtcTime) -> chrono::NaiveDateTime {
let d = chrono::NaiveDate::from_ymd(
rtc.tm_year as i32 + YEAR_EPOCH,
(rtc.tm_mon + 1) as u32,
rtc.tm_mday as u32,
);
let t =
chrono::NaiveTime::from_hms(rtc.tm_hour as u32, rtc.tm_min as u32, rtc.tm_sec as u32);
chrono::NaiveDateTime::new(d, t)
}
}
impl From<chrono::NaiveDateTime> for RtcTime {
fn from(ct: chrono::NaiveDateTime) -> RtcTime {
RtcTime {
tm_sec: ct.time().second() as i32,
tm_min: ct.time().minute() as i32,
tm_hour: ct.time().hour() as i32,
tm_mday: ct.date().day() as i32,
tm_mon: ct.date().month0() as i32,
tm_year: ct.date().year() - YEAR_EPOCH,
..RtcTime::default()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn conversion_from_rtctime() {
let rtc = RtcTime {
tm_sec: 1,
tm_min: 6,
tm_hour: 14,
tm_mday: 19,
tm_mon: 1,
tm_year: 118,
tm_wday: 0,
tm_yday: 0,
tm_isdst: 0,
};
let ct = chrono::NaiveDateTime::new(
chrono::NaiveDate::from_ymd(2018, 2, 19),
chrono::NaiveTime::from_hms(14, 6, 1),
);
let rtc_from_ct: RtcTime = ct.into();
let ct_from_rtc: chrono::NaiveDateTime = rtc.into();
assert_eq!(rtc, rtc_from_ct);
assert_eq!(ct, ct_from_rtc);
}
#[test]
fn bindgen_test_layout_rtc_time() {
assert_eq!(
::std::mem::size_of::<RtcTime>(),
36usize,
concat!("Size of: ", stringify!(RtcTime))
);
assert_eq!(
::std::mem::align_of::<RtcTime>(),
4usize,
concat!("Alignment of ", stringify!(RtcTime))
);
}
}
#[derive(Debug)]
pub struct HwClockDev {
clk: fs::File,
}
impl HwClockDev {
pub fn open<P: AsRef<path::Path>>(dev: P) -> io::Result<HwClockDev> {
Ok(HwClockDev {
clk: fs::File::open(dev)?,
})
}
pub fn get_time(&self) -> Result<RtcTime, nix::Error> {
let mut time = RtcTime::default();
assert_eq!(0, unsafe {
ffi::rtc_rd_time(self.clk.as_raw_fd(), &mut time as *mut RtcTime)
}?);
Ok(time)
}
pub fn set_time(&self, time: &RtcTime) -> Result<(), nix::Error> {
assert_eq!(0, unsafe {
ffi::rtc_set_time(self.clk.as_raw_fd(), time as *const RtcTime)
}?);
Ok(())
}
}