use displaydoc::Display;
use thiserror::Error;
use crate::{
Mmc,
mmc::{Cdb, MmcCommand, MmcDirection, MmcError},
};
impl Mmc {
pub fn eject(&self) -> Result<(), MmcEjectError> {
self.start_stop_unit(StartStopOperation::EjectDisc)?;
Ok(())
}
pub fn close_tray(&self) -> Result<(), MmcCloseTrayError> {
self.start_stop_unit(StartStopOperation::LoadStartDisc)?;
Ok(())
}
pub fn set_power_state(&self, state: PowerCondition) -> Result<(), MmcSetPowerStateError> {
self.start_stop_unit(StartStopOperation::Power(state))?;
Ok(())
}
fn start_stop_unit(&self, operation: StartStopOperation) -> Result<(), MmcStartStopError> {
let mut cdb = Cdb::default();
cdb[0] = MmcCommand::StartStopUnit as u8;
cdb[1] = 0; if let StartStopOperation::Jump { layer_number } = operation {
cdb[3] = layer_number & LAYER_NUM_BITMASK;
cdb[4] |= 1 << FORMAT_LAYER_BITPOS;
}
cdb[4] |= match operation {
StartStopOperation::StartDisc => 0b01,
StartStopOperation::EjectDisc => 0b10,
StartStopOperation::LoadStartDisc | StartStopOperation::Jump { .. } => 0b11,
_ => 0b00,
};
if let StartStopOperation::Power(pow_cond) = operation {
cdb[4] |= (pow_cond as u8 & POWER_COND_BITMASK) << POWER_COND_BITPOS;
}
self.run_command(Some(MmcDirection::Write), &mut [], cdb)?;
return Ok(());
const LAYER_NUM_BITMASK: u8 = 0b11;
const FORMAT_LAYER_BITPOS: usize = 2;
const POWER_COND_BITMASK: u8 = 0b1111;
const POWER_COND_BITPOS: usize = 4;
}
}
#[derive(Debug, Display, Error)]
pub struct MmcEjectError {
#[from]
pub source: MmcStartStopError,
}
#[derive(Debug, Display, Error)]
pub struct MmcCloseTrayError {
#[from]
pub source: MmcStartStopError,
}
#[derive(Debug, Display, Error)]
pub struct MmcSetPowerStateError {
#[from]
pub source: MmcStartStopError,
}
#[derive(Debug, Display, Error)]
pub struct MmcStartStopError {
#[from]
pub source: MmcError,
}
#[allow(unused)]
enum StartStopOperation {
StopDisc,
StartDisc,
EjectDisc,
LoadStartDisc,
Jump {
layer_number: u8,
},
Power(PowerCondition),
}
#[allow(unused)]
pub enum PowerCondition {
Idle = 0x2,
Standby = 0x3,
Sleep = 0x5,
}