lesavka/server/src/bin/lesavka_uvc/coverage_startup.rs

129 lines
3.6 KiB
Rust
Raw Normal View History

fn main() -> Result<()> {
let (dev, _cfg) = parse_args()?;
let _ = load_interfaces();
let _ = UvcConfig::from_env();
let _ = open_with_retry(&dev)?;
anyhow::bail!("coverage harness: control loop disabled");
}
#[cfg(coverage)]
fn parse_args() -> Result<(String, UvcConfig)> {
let args: Vec<String> = env::args().skip(1).collect();
let dev = parse_device_arg(&args)
.or_else(|| env::var("LESAVKA_UVC_DEV").ok())
.context("missing --device (or LESAVKA_UVC_DEV)")?;
Ok((dev, UvcConfig::from_env()))
}
#[cfg(coverage)]
fn parse_device_arg(args: &[String]) -> Option<String> {
args
.windows(2)
.find_map(|pair| (pair[0] == "--device" || pair[0] == "-d").then(|| pair[1].clone()))
.or_else(|| {
args.iter()
.rev()
.find(|arg| {
arg.as_str() != "--device" && arg.as_str() != "-d" && arg.starts_with('/')
})
.cloned()
})
}
#[cfg(coverage)]
impl UvcConfig {
fn from_env() -> Self {
let width = env_u32("LESAVKA_UVC_WIDTH", 1280);
let height = env_u32("LESAVKA_UVC_HEIGHT", 720);
let fps = env_u32("LESAVKA_UVC_FPS", 25).max(1);
let frame_size = env_u32("LESAVKA_UVC_FRAME_SIZE", width * height * 2);
let interval = env_u32("LESAVKA_UVC_INTERVAL", 0);
let bulk = env::var("LESAVKA_UVC_BULK").is_ok();
let mut max_packet = env_u32("LESAVKA_UVC_MAXPACKET", 1024);
if let Some(limit) = compute_payload_cap(bulk).map(|cap| cap.limit) {
max_packet = max_packet.min(limit);
}
max_packet = if bulk {
max_packet.min(512)
} else {
max_packet.min(1024)
};
let interval = if interval == 0 {
10_000_000 / fps
} else {
interval
};
Self {
width,
height,
fps,
interval,
max_packet,
frame_size,
}
}
}
#[cfg(coverage)]
impl UvcState {
fn new(cfg: UvcConfig) -> Self {
let ctrl_len = stream_ctrl_len();
let default = build_streaming_control(&cfg, ctrl_len);
Self {
cfg,
ctrl_len,
default,
probe: default,
commit: default,
cfg_snapshot: None,
}
}
}
#[cfg(coverage)]
fn load_interfaces() -> UvcInterfaces {
let control = env_u8("LESAVKA_UVC_CTRL_INTF").unwrap_or(UVC_STRING_CONTROL_IDX);
let streaming = env_u8("LESAVKA_UVC_STREAM_INTF").unwrap_or(UVC_STRING_STREAMING_IDX);
UvcInterfaces { control, streaming }
}
#[cfg(coverage)]
fn read_interface(path: &str) -> Option<u8> {
std::fs::read_to_string(path)
.ok()
.and_then(|v| v.trim().parse::<u8>().ok())
}
#[cfg(coverage)]
fn open_with_retry(path: &str) -> Result<std::fs::File> {
let read_only = uvc_control_read_only();
let mut opts = OpenOptions::new();
opts.read(true);
if !read_only {
opts.write(true);
}
if env::var("LESAVKA_UVC_BLOCKING").is_err() {
opts.custom_flags(libc::O_NONBLOCK);
}
opts.open(path).with_context(|| format!("open {path}"))
}
#[cfg(coverage)]
fn uvc_control_read_only() -> bool {
env::var("LESAVKA_UVC_CONTROL_READ_ONLY")
.ok()
.map(|value| {
let trimmed = value.trim();
!(trimmed.eq_ignore_ascii_case("0")
|| trimmed.eq_ignore_ascii_case("false")
|| trimmed.eq_ignore_ascii_case("no")
|| trimmed.eq_ignore_ascii_case("off"))
})
.unwrap_or(true)
}