libcdio_rs/mmc/
start_stop_unit.rs1use displaydoc::Display;
21use thiserror::Error;
22
23use crate::{
24 Mmc,
25 mmc::{Cdb, MmcCommand, MmcDirection, MmcError},
26};
27
28impl Mmc {
30 pub fn eject(&self) -> Result<(), MmcEjectError> {
34 self.start_stop_unit(StartStopOperation::EjectDisc)?;
35 Ok(())
36 }
37
38 pub fn close_tray(&self) -> Result<(), MmcCloseTrayError> {
40 self.start_stop_unit(StartStopOperation::LoadStartDisc)?;
41 Ok(())
42 }
43
44 pub fn set_power_state(&self, state: PowerCondition) -> Result<(), MmcSetPowerStateError> {
46 self.start_stop_unit(StartStopOperation::Power(state))?;
47 Ok(())
48 }
49
50 fn start_stop_unit(&self, operation: StartStopOperation) -> Result<(), MmcStartStopError> {
51 let mut cdb = Cdb::default();
52
53 cdb[0] = MmcCommand::StartStopUnit as u8;
54 cdb[1] = 0; if let StartStopOperation::Jump { layer_number } = operation {
56 cdb[3] = layer_number & LAYER_NUM_BITMASK;
57 cdb[4] |= 1 << FORMAT_LAYER_BITPOS;
58 }
59 cdb[4] |= match operation {
62 StartStopOperation::StartDisc => 0b01,
63 StartStopOperation::EjectDisc => 0b10,
64 StartStopOperation::LoadStartDisc | StartStopOperation::Jump { .. } => 0b11,
65 _ => 0b00,
66 };
67 if let StartStopOperation::Power(pow_cond) = operation {
68 cdb[4] |= (pow_cond as u8 & POWER_COND_BITMASK) << POWER_COND_BITPOS;
69 }
70
71 self.run_command(Some(MmcDirection::Write), &mut [], cdb)?;
72
73 return Ok(());
74
75 const LAYER_NUM_BITMASK: u8 = 0b11;
76 const FORMAT_LAYER_BITPOS: usize = 2;
77 const POWER_COND_BITMASK: u8 = 0b1111;
78 const POWER_COND_BITPOS: usize = 4;
79 }
80}
81
82#[derive(Debug, Display, Error)]
84pub struct MmcEjectError {
85 #[from]
86 pub source: MmcStartStopError,
87}
88
89#[derive(Debug, Display, Error)]
91pub struct MmcCloseTrayError {
92 #[from]
93 pub source: MmcStartStopError,
94}
95
96#[derive(Debug, Display, Error)]
98pub struct MmcSetPowerStateError {
99 #[from]
100 pub source: MmcStartStopError,
101}
102
103#[derive(Debug, Display, Error)]
105pub struct MmcStartStopError {
106 #[from]
107 pub source: MmcError,
108}
109
110#[allow(unused)]
112enum StartStopOperation {
113 StopDisc,
114 StartDisc,
115 EjectDisc,
116 LoadStartDisc,
117
118 Jump {
121 layer_number: u8,
122 },
123
124 Power(PowerCondition),
126}
127
128#[allow(unused)]
130pub enum PowerCondition {
131 Idle = 0x2,
132 Standby = 0x3,
133 Sleep = 0x5,
134}
135
136