Skip to main content

basic/
basic.rs

1//! Demonstrates the clock-steering library.
2//!
3//! Usage: cargo run --example basic [realtime|tai|/dev/ptpN]
4//!
5//! Write operations (frequency, step, leap seconds, TAI) require root privileges.
6
7use clock_steering::unix::UnixClock;
8use statime_base::{Clock, Duration, LeapStatus, Timestamp};
9
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11    #[cfg(target_os = "linux")]
12    let arg = std::env::args().nth(1);
13
14    #[cfg(target_os = "linux")]
15    match arg.as_deref() {
16        None | Some("realtime") => exercise_clock(UnixClock::CLOCK_REALTIME),
17        Some("tai") => exercise_clock(UnixClock::CLOCK_TAI),
18        Some(path) if path.starts_with("/dev/") => exercise_clock(UnixClock::open(path)?),
19        Some(other) => {
20            eprintln!("unknown clock: {other}");
21            eprintln!("usage: basic [realtime|tai|/dev/ptpN]");
22            std::process::exit(1);
23        }
24    }
25
26    #[cfg(not(target_os = "linux"))]
27    exercise_clock(UnixClock::CLOCK_REALTIME)
28}
29
30fn exercise_clock<Timescale: Send + 'static>(
31    clock: UnixClock<Timescale>,
32) -> Result<(), Box<dyn std::error::Error>> {
33    // Read-only operations
34
35    let now = clock.now()?;
36    let nanos = (now - Timestamp::UNIX_EPOCH).as_nanos();
37    let seconds = nanos / 1_000_000_000;
38    let nanos = nanos % 1_000_000_000;
39    println!("now:         {}.{:09}", seconds, nanos);
40
41    let res = clock.resolution()?;
42    println!("resolution:  {}ns", res.as_nanos());
43
44    let max_freq = clock.max_frequency()?;
45    println!("max freq:    {} ppm", max_freq * 1e6);
46
47    match clock.get_frequency() {
48        Ok(f) => println!("frequency:   {:.6} us/s", f * 1e6),
49        Err(e) => println!("frequency:   {e}"),
50    }
51
52    #[cfg(target_os = "linux")]
53    match clock.get_tai() {
54        Ok(tai) => println!("TAI offset:  {tai}s"),
55        Err(e) => println!("TAI offset:  {e}"),
56    }
57
58    // Write operations — require root
59
60    println!();
61
62    match clock.set_frequency(0.0) {
63        Ok(t) => println!(
64            "set_frequency(0.0):     ok at {}.{:09}",
65            (t - Timestamp::UNIX_EPOCH).as_nanos() / 1_000_000_000,
66            (t - Timestamp::UNIX_EPOCH).as_nanos() % 1_000_000_000
67        ),
68        Err(e) => println!("set_frequency(0.0):     {e}"),
69    }
70
71    match clock.step_clock(Duration::from_seconds_nanos(0, 0)) {
72        Ok(t) => println!(
73            "step_clock(0):          ok at {}.{:09}",
74            (t - Timestamp::UNIX_EPOCH).as_nanos() / 1_000_000_000,
75            (t - Timestamp::UNIX_EPOCH).as_nanos() % 1_000_000_000
76        ),
77        Err(e) => println!("step_clock(0):          {e}"),
78    }
79
80    match clock.leap_update(LeapStatus::None) {
81        Ok(()) => println!("set_leap_seconds:       ok"),
82        Err(e) => println!("set_leap_seconds:       {e}"),
83    }
84
85    match clock.error_estimate_update(
86        Duration::from_seconds_nanos(0, 100_000),
87        Duration::from_seconds_nanos(0, 1_000_000),
88    ) {
89        Ok(()) => println!("error_estimate_update:  ok"),
90        Err(e) => println!("error_estimate_update:  {e}"),
91    }
92
93    match clock.disable_kernel() {
94        Ok(()) => println!("disable_kernel_ntp:     ok"),
95        Err(e) => println!("disable_kernel_ntp:     {e}"),
96    }
97
98    Ok(())
99}