use std::convert::Infallible;
use crate::{error::PlatformError, ChipImpl};
use status::InitStatus;
pub mod status;
pub enum CallReason<'a> {
NewChip,
NotNew,
InitWait(&'a InitStatus),
ChipInitCompleted(&'a InitStatus),
}
#[allow(dead_code)]
pub struct ChipDetectState<'a> {
pub chip: &'a dyn ChipImpl,
pub call: CallReason<'a>,
}
#[derive(thiserror::Error)]
pub enum InitError<E> {
#[error(transparent)]
PlatformError(#[from] PlatformError),
CallbackError(E),
}
impl Into<PlatformError> for InitError<Infallible> {
fn into(self) -> PlatformError {
match self {
InitError::PlatformError(err) => err,
InitError::CallbackError(_) => unreachable!(),
}
}
}
pub fn wait_for_init<E>(
chip: &mut impl ChipImpl,
callback: &mut impl FnMut(ChipDetectState) -> Result<(), E>,
allow_failure: bool,
noc_safe: bool,
) -> Result<InitStatus, InitError<E>> {
callback(ChipDetectState {
chip,
call: CallReason::NewChip,
})
.map_err(|v| InitError::CallbackError(v))?;
let mut status = InitStatus::new_unknown();
status.init_options.noc_safe = noc_safe;
loop {
match chip.update_init_state(&mut status)? {
super::ChipInitResult::NoError => {
}
super::ChipInitResult::ErrorContinue => {
if !allow_failure {
return Err(PlatformError::Generic(
"Chip initialization failed".to_string(),
crate::error::BtWrapper::capture(),
))?;
} else {
callback(ChipDetectState {
chip,
call: CallReason::ChipInitCompleted(&status),
})
.map_err(InitError::CallbackError)?;
return Ok(status);
}
}
super::ChipInitResult::ErrorAbort => {
return Err(PlatformError::Generic(
"Chip initialization failed (aborted)".to_string(),
crate::error::BtWrapper::capture(),
))?;
}
}
let call = if !status.init_complete() {
CallReason::InitWait(&status)
} else {
callback(ChipDetectState {
chip,
call: CallReason::ChipInitCompleted(&status),
})
.map_err(InitError::CallbackError)?;
return Ok(status);
};
callback(ChipDetectState { chip, call }).map_err(InitError::CallbackError)?;
}
}