From caf313414c894e919bff618e48aaac42d0b2878e Mon Sep 17 00:00:00 2001 From: louib Date: Sat, 4 Oct 2025 10:05:00 -0400 Subject: [PATCH] feat: add support for reading config --- examples/is_configured.rs | 26 ++++++++++++++++++++++ examples/read_status.rs | 47 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 39 +++++++++++++++++++++++++++++++- src/usb.rs | 10 +++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 examples/is_configured.rs create mode 100644 examples/read_status.rs diff --git a/examples/is_configured.rs b/examples/is_configured.rs new file mode 100644 index 0000000..16085cb --- /dev/null +++ b/examples/is_configured.rs @@ -0,0 +1,26 @@ +use challenge_response::{config::Slot, ChallengeResponse, Device}; + +fn main() { + let mut cr = ChallengeResponse::new().unwrap(); + let device = cr.find_device().unwrap(); + + println!("Checking configuration for device: {:?}", device.name); + + check_slot(&mut cr, &device, Slot::Slot1); + check_slot(&mut cr, &device, Slot::Slot2); +} + +fn check_slot(cr: &mut ChallengeResponse, device: &Device, slot: Slot) { + match cr.is_configured(device.clone(), slot.clone()) { + Ok(configured) => { + println!( + "Slot {:?} is {}configured", + slot, + if configured { "" } else { "not " } + ); + } + Err(e) => { + eprintln!("Error checking slot {:?}: {:?}", slot, e); + } + } +} diff --git a/examples/read_status.rs b/examples/read_status.rs new file mode 100644 index 0000000..3f27f78 --- /dev/null +++ b/examples/read_status.rs @@ -0,0 +1,47 @@ +use challenge_response::{config::Config, ChallengeResponse}; + +fn main() { + let mut cr = ChallengeResponse::new().expect("Failed to initialize ChallengeResponse"); + + match cr.find_device() { + Ok(device) => { + println!("Found device: {:?}", device.name.as_deref().unwrap_or("Unknown")); + println!("Serial: {:?}", device.serial); + + let conf = Config::new_from(device); + match cr.read_status(conf) { + Ok(status) => { + println!("--- Device Status ---"); + println!( + "Firmware Version: {}.{}.{}", + status.version_major, status.version_minor, status.version_build + ); + println!("Programming Sequence: {}", status.pgm_seq); + println!("Touch Level: 0x{:04x}", status.touch_level); + + let slot1_configured = (status.touch_level & 1) != 0; + let slot2_configured = (status.touch_level & 2) != 0; + + println!( + "Slot 1: {}", + if slot1_configured { + "Configured" + } else { + "Not configured" + } + ); + println!( + "Slot 2: {}", + if slot2_configured { + "Configured" + } else { + "Not configured" + } + ); + } + Err(e) => eprintln!("Error reading status: {:?}", e), + } + } + Err(e) => eprintln!("No device found: {:?}", e), + } +} diff --git a/src/lib.rs b/src/lib.rs index 49c3cdc..e5aa822 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ use error::ChallengeResponseError; use hmacmode::Hmac; use otpmode::Aes128Block; use sec::{crc16, CRC_RESIDUAL_OK}; -use usb::{Backend, BackendType, Flags, Frame, CHALLENGE_SIZE}; +use usb::{Backend, BackendType, Flags, Frame, Status, CHALLENGE_SIZE}; pub use usb::Device; @@ -71,6 +71,43 @@ impl ChallengeResponse { .read_serial_from_device(conf.device.bus_id, conf.device.address_id) } + pub fn read_status(&mut self, conf: Config) -> Result { + let (mut handle, interfaces) = self + .backend + .open_device(conf.device.bus_id, conf.device.address_id)?; + + // Read the response. + let mut response = [0; 8]; + self.backend.read(&mut handle, &mut response)?; + self.backend.close_device(handle, interfaces)?; + + let status = Status { + version_major: response[1], + version_minor: response[2], + version_build: response[3], + pgm_seq: response[4], + touch_level: u16::from_le_bytes([response[5], response[6]]), + }; + + Ok(status) + } + + pub fn is_configured(&mut self, device: Device, slot: Slot) -> Result { + let conf = Config::new_from(device); + let status = self.read_status(conf)?; + + if status.pgm_seq == 0 { + return Ok(false); + } + + let configured = match slot { + Slot::Slot1 => (status.touch_level & 1) != 0, + Slot::Slot2 => (status.touch_level & 2) != 0, + }; + + Ok(configured) + } + pub fn write_config(&mut self, conf: Config, device_config: &mut DeviceModeConfig) -> Result<()> { let d = device_config.to_frame(conf.command); let mut buf = [0; usb::STATUS_UPDATE_PAYLOAD_SIZE]; diff --git a/src/usb.rs b/src/usb.rs index 98c8290..681c64f 100644 --- a/src/usb.rs +++ b/src/usb.rs @@ -61,6 +61,16 @@ pub struct Frame { filler: [u8; 3], } +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct Status { + pub version_major: u8, + pub version_minor: u8, + pub version_build: u8, + pub pgm_seq: u8, + pub touch_level: u16, +} + impl Frame { pub fn new(payload: [u8; PAYLOAD_SIZE], command: Command) -> Self { let mut f = Frame {