use crate::device::{Device, DeviceError};
use crate::transports::Transport;
use sha2::{Digest, Sha256};
#[derive(Default)]
pub struct FlashOptions<'a> {
pub chunk_size: Option<usize>,
pub sha256: Option<&'a [u8]>,
pub on_progress: Option<&'a mut dyn FnMut(usize, usize)>,
}
pub fn flash<T: Transport>(
device: &mut Device<T>,
firmware: &[u8],
mut opts: FlashOptions<'_>,
) -> Result<(), DeviceError<T::Error>> {
let total = firmware.len();
if total == 0 {
return Err(DeviceError::WireError(crate::wire::WireError::IncompletePkt));
}
let mut digest_buf = [0u8; 32];
let digest: &[u8] = match opts.sha256 {
Some(s) if s.len() == 32 => s,
Some(_) => return Err(DeviceError::WireError(crate::wire::WireError::IncompletePkt)),
None => {
let h = Sha256::digest(firmware);
digest_buf.copy_from_slice(&h);
&digest_buf
}
};
let chunk_size = opts.chunk_size.unwrap_or(240);
device.ota_begin(total as u32, digest)?;
let mut sent = 0usize;
while sent < total {
let end = core::cmp::min(sent + chunk_size, total);
device.ota_chunk(sent as u32, &firmware[sent..end])?;
sent = end;
if let Some(cb) = opts.on_progress.as_deref_mut() {
cb(sent, total);
}
}
device.ota_finalize()?;
Ok(())
}