mirror of
https://github.com/cjfranko/NTP-Timeturner.git
synced 2025-11-08 18:32:02 +00:00
feat: add Statime daemon integration for Linux and non-Linux stubs
Co-authored-by: aider (openai/gpt-5) <aider@aider.chat>
This commit is contained in:
parent
323cc61ae3
commit
0239b56c1a
2 changed files with 164 additions and 0 deletions
|
|
@ -22,6 +22,7 @@ daemonize = "0.5.0"
|
|||
num-rational = "0.4"
|
||||
num-traits = "0.2"
|
||||
libc = "0.2"
|
||||
which = "6"
|
||||
|
||||
[[bin]]
|
||||
name = "ptp_probe"
|
||||
|
|
|
|||
163
src/ptp.rs
163
src/ptp.rs
|
|
@ -121,3 +121,166 @@ pub use linux::{is_supported, PtpClock};
|
|||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub use non_linux::{is_supported, PtpClock};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Statime daemon integration
|
||||
// This provides a thin wrapper to spawn and manage the 'statime' PTP daemon
|
||||
// as a child process from within this application (Linux only).
|
||||
// On non-Linux targets, it returns PtpError::Unsupported.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
mod statime_linux_mod {
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Child, Command, Stdio};
|
||||
|
||||
use super::PtpError;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StatimeOptions {
|
||||
pub interface: String,
|
||||
pub phc_index: Option<u32>,
|
||||
pub extra_args: Vec<String>,
|
||||
}
|
||||
|
||||
impl StatimeOptions {
|
||||
pub fn new<S: Into<String>>(interface: S) -> Self {
|
||||
Self {
|
||||
interface: interface.into(),
|
||||
phc_index: None,
|
||||
extra_args: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn with_phc_index(mut self, idx: u32) -> Self {
|
||||
self.phc_index = Some(idx);
|
||||
self
|
||||
}
|
||||
pub fn with_args<I, S>(mut self, args: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
{
|
||||
self.extra_args = args.into_iter().map(|s| s.into()).collect();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StatimeDaemon {
|
||||
child: Child,
|
||||
}
|
||||
|
||||
impl StatimeDaemon {
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
self.child.try_wait().ok().flatten().is_none()
|
||||
}
|
||||
pub fn pid(&self) -> u32 {
|
||||
self.child.id()
|
||||
}
|
||||
pub fn stop(&mut self) -> Result<(), PtpError> {
|
||||
self.child.kill().map_err(PtpError::Io)?;
|
||||
let _ = self.child.wait();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StatimeDaemon {
|
||||
fn drop(&mut self) {
|
||||
let _ = self.stop();
|
||||
}
|
||||
}
|
||||
|
||||
fn find_statime_binary() -> Result<PathBuf, io::Error> {
|
||||
which::which("statime").or_else(|_| {
|
||||
let fallback = PathBuf::from("/usr/local/bin/statime");
|
||||
if fallback.exists() {
|
||||
Ok(fallback)
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::NotFound,
|
||||
"statime binary not found in PATH or /usr/local/bin",
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn spawn_statime(opts: StatimeOptions) -> Result<StatimeDaemon, PtpError> {
|
||||
let bin = find_statime_binary().map_err(PtpError::Io)?;
|
||||
|
||||
let mut cmd = Command::new(bin);
|
||||
cmd.arg("-i").arg(&opts.interface);
|
||||
|
||||
if let Some(idx) = opts.phc_index {
|
||||
// Prefer --phc-index if supported by the installed statime version.
|
||||
cmd.arg("--phc-index").arg(idx.to_string());
|
||||
}
|
||||
|
||||
for a in &opts.extra_args {
|
||||
cmd.arg(a);
|
||||
}
|
||||
|
||||
// Inherit stdio for visibility; detach stdin.
|
||||
cmd.stdin(Stdio::null())
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit());
|
||||
|
||||
let child = cmd.spawn().map_err(PtpError::Io)?;
|
||||
Ok(StatimeDaemon { child })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
mod statime_nonlinux_mod {
|
||||
use super::PtpError;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct StatimeOptions {
|
||||
pub interface: String,
|
||||
pub phc_index: Option<u32>,
|
||||
pub extra_args: Vec<String>,
|
||||
}
|
||||
|
||||
impl StatimeOptions {
|
||||
pub fn new<S: Into<String>>(interface: S) -> Self {
|
||||
Self {
|
||||
interface: interface.into(),
|
||||
phc_index: None,
|
||||
extra_args: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn with_phc_index(self, _idx: u32) -> Self {
|
||||
self
|
||||
}
|
||||
pub fn with_args<I, S>(self, _args: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: Into<String>,
|
||||
{
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct StatimeDaemon;
|
||||
|
||||
impl StatimeDaemon {
|
||||
pub fn is_running(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
pub fn pid(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
pub fn stop(&mut self) -> Result<(), PtpError> {
|
||||
Err(PtpError::Unsupported)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn spawn_statime(_opts: StatimeOptions) -> Result<StatimeDaemon, PtpError> {
|
||||
Err(PtpError::Unsupported)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub use statime_linux_mod::{spawn_statime, StatimeDaemon, StatimeOptions};
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub use statime_nonlinux_mod::{spawn_statime, StatimeDaemon, StatimeOptions};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue