-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3db67f7
commit 3e7bf2a
Showing
7 changed files
with
418 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/target |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
name = "pps-time" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
libc = "0.2.168" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# PPS Time | ||
A Rust interface for Pulse Per Second (PPS) devices, based on [RFC 2783](https://datatracker.ietf.org/doc/html/rfc2783). This crate is part of [Project Pendulum](https://github.com/pendulum-project), and is used in [ntpd-rs](https://github.com/pendulum-project/ntpd-rs). | ||
|
||
The `pps.rs` contains bindings that were automatically generated by rust-bindgen: | ||
``` | ||
bindgen /usr/include/linux/pps.h -o ./src/pps.rs --with-derive-default --raw-line '#![allow(dead_code, non_camel_case_types)]' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
use std::{ | ||
fs::File, | ||
io::Error, | ||
mem::MaybeUninit, | ||
os::{ | ||
fd::AsRawFd, | ||
raw::{c_uint, c_ulong}, | ||
}, | ||
path::PathBuf, | ||
}; | ||
|
||
pub mod pps; | ||
use pps::{pps_fdata, pps_kparams, pps_ktime, PPS_TIME_INVALID}; | ||
|
||
// These constants rely on macros which bindgen does not export from pps.h | ||
const PPS_GETPARAMS: c_ulong = 0x800870a1; | ||
const PPS_SETPARAMS: c_ulong = 0x400870a2; | ||
const PPS_GETCAP: c_ulong = 0x800870a3; | ||
const PPS_FETCH: c_ulong = 0xc00870a4; | ||
|
||
pub struct PpsDevice(File); | ||
|
||
impl PpsDevice { | ||
pub fn new(path: PathBuf) -> Result<PpsDevice, Error> { | ||
Ok(PpsDevice(File::open(path)?)) | ||
} | ||
|
||
/// Perform ioctl request and check result for possible errors | ||
unsafe fn ioctl<T>(&self, request: c_ulong, value: &mut T) -> Result<(), Error> { | ||
let result = libc::ioctl(self.0.as_raw_fd(), request, value); | ||
if result != 0 { | ||
return Err(Error::last_os_error()); | ||
} | ||
Ok(()) | ||
} | ||
|
||
/// Perform ioctl request with uninitialized data | ||
unsafe fn ioctl_uninit<T>(&self, request: c_ulong) -> Result<T, Error> { | ||
let mut value: MaybeUninit<T> = MaybeUninit::uninit(); | ||
self.ioctl(request, &mut value)?; | ||
Ok(unsafe { value.assume_init() }) | ||
} | ||
|
||
pub fn get_params(&self) -> Result<pps_kparams, Error> { | ||
unsafe { self.ioctl_uninit(PPS_GETPARAMS) } | ||
} | ||
|
||
pub fn set_params(&self, params: &mut pps_kparams) -> Result<(), Error> { | ||
unsafe { self.ioctl(PPS_SETPARAMS, params) } | ||
} | ||
|
||
pub fn get_cap(&self) -> Result<c_uint, Error> { | ||
unsafe { self.ioctl_uninit(PPS_GETCAP) } | ||
} | ||
|
||
pub fn fetch(&self, timeout: Option<pps_ktime>) -> Result<pps_fdata, Error> { | ||
let timeout = timeout.unwrap_or(pps_ktime { | ||
sec: 0, | ||
nsec: 0, | ||
flags: PPS_TIME_INVALID, | ||
}); | ||
|
||
let mut data = pps_fdata { | ||
info: Default::default(), | ||
timeout, | ||
}; | ||
|
||
unsafe { self.ioctl(PPS_FETCH, &mut data)? }; | ||
|
||
Ok(data) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
use pps_time::{pps, PpsDevice}; | ||
use std::path::PathBuf; | ||
|
||
/// A simple PPS demo program | ||
fn main() { | ||
let args: Vec<String> = std::env::args().collect(); | ||
if args.len() < 2 { | ||
println!("Example usage:"); | ||
println!("$ sudo ./target/debug/pps-time /dev/pps0"); | ||
return; | ||
} | ||
|
||
let path = PathBuf::from(&args[1]); // path to PPS device | ||
|
||
println!("Opening PPS device {}", path.display()); | ||
let pps = PpsDevice::new(path).expect("Could not open file!"); | ||
|
||
let capabilities = pps.get_cap().expect("Could not get capabilities!"); | ||
println!("Capabilities: {:#x}", capabilities); | ||
|
||
let mut params = pps.get_params().expect("Could not get params!"); | ||
println!("{:?}", params); | ||
|
||
// Turn on CAPTUREASSERT if available | ||
if capabilities & pps::PPS_CAPTUREASSERT != 0 { | ||
params.mode |= pps::PPS_CAPTUREASSERT as i32; | ||
} else { | ||
println!("Cannot CAPTUREASSERT"); | ||
} | ||
// Turn on CAPTURECLEAR if available | ||
if capabilities & pps::PPS_CAPTURECLEAR != 0 { | ||
params.mode |= pps::PPS_CAPTURECLEAR as i32; | ||
} else { | ||
println!("Cannot CAPTURECLEAR"); | ||
} | ||
|
||
pps.set_params(&mut params).expect("Could not set params!"); | ||
|
||
if capabilities & pps::PPS_CANWAIT == 0 { | ||
println!("Cannot CANWAIT"); | ||
return; | ||
} | ||
|
||
loop { | ||
let data = pps.fetch(None).expect("Could not fetch!"); | ||
println!("{:#?}", data); | ||
} | ||
} |
Oops, something went wrong.