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 = 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 { 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", 30).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 { std::fs::read_to_string(path) .ok() .and_then(|v| v.trim().parse::().ok()) } #[cfg(coverage)] fn open_with_retry(path: &str) -> Result { 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)] /// Keep coverage-mode UVC control opens read-only unless a test opts into writes. 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) }