1use std::{
2 fs::File,
3 io::{Error, Result},
4 mem::MaybeUninit,
5 os::{
6 fd::AsRawFd,
7 raw::{c_uint, c_ulong},
8 },
9 path::PathBuf,
10};
11
12pub mod pps;
13use pps::{pps_fdata, pps_kparams, pps_ktime, PPS_TIME_INVALID};
14
15const PPS_GETPARAMS: c_ulong = 0x800870a1;
17const PPS_SETPARAMS: c_ulong = 0x400870a2;
18const PPS_GETCAP: c_ulong = 0x800870a3;
19const PPS_FETCH: c_ulong = 0xc00870a4;
20
21pub struct PpsDevice(File);
22
23impl PpsDevice {
24 pub fn new(path: PathBuf) -> Result<PpsDevice> {
25 Ok(PpsDevice(File::open(path)?))
26 }
27
28 unsafe fn ioctl<T>(&self, request: c_ulong, value: &mut T) -> Result<()> {
30 match libc::ioctl(self.0.as_raw_fd(), request as _, value) {
31 0 => Ok(()),
32 _ => Err(Error::last_os_error()),
33 }
34 }
35
36 unsafe fn ioctl_uninit<T>(&self, request: c_ulong) -> Result<T> {
38 let mut value: MaybeUninit<T> = MaybeUninit::uninit();
39 self.ioctl(request, &mut value)?;
40 Ok(unsafe { value.assume_init() })
41 }
42
43 pub fn get_params(&self) -> Result<pps_kparams> {
44 unsafe { self.ioctl_uninit(PPS_GETPARAMS) }
46 }
47
48 pub fn set_params(&self, params: &mut pps_kparams) -> Result<()> {
49 unsafe { self.ioctl(PPS_SETPARAMS, params) }
51 }
52
53 pub fn get_cap(&self) -> Result<c_uint> {
54 unsafe { self.ioctl_uninit(PPS_GETCAP) }
56 }
57
58 fn fetch(&self, timeout: pps_ktime) -> Result<pps_fdata> {
59 let mut data = pps_fdata {
60 info: Default::default(),
61 timeout,
62 };
63
64 unsafe { self.ioctl(PPS_FETCH, &mut data)? };
66
67 Ok(data)
68 }
69
70 pub fn fetch_blocking(&self) -> Result<pps_fdata> {
74 self.fetch(pps_ktime {
75 sec: 0,
76 nsec: 0,
77 flags: PPS_TIME_INVALID,
78 })
79 }
80
81 pub fn fetch_timeout(&self, seconds: i64, nanoseconds: i32) -> Result<pps_fdata> {
85 self.fetch(pps_ktime {
86 sec: seconds,
87 nsec: nanoseconds,
88 flags: 0,
89 })
90 }
91
92 pub fn fetch_non_blocking(&self) -> Result<pps_fdata> {
94 self.fetch(pps_ktime {
95 sec: 0,
96 nsec: 0,
97 flags: 0,
98 })
99 }
100}