From 4a76d96341ffe18a74bf01b9430f579350105950 Mon Sep 17 00:00:00 2001 From: G2-Games Date: Sat, 23 Sep 2023 15:06:48 -0500 Subject: [PATCH] Added more functions to interface, cleaned up `base.rs` --- Cargo.toml | 1 + src/main.rs | 17 ++++-- src/netmd/base.rs | 75 +++++++++++------------ src/netmd/interface.rs | 131 ++++++++++++++++++++++++++++++++++++++++- src/netmd/utils.rs | 27 +++++++++ 5 files changed, 206 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 48877a5..c2fa763 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +bcd-numbers = "1.0.11" nofmt = "1.0.0" once_cell = "1.18.0" rusb = "0.9.3" diff --git a/src/main.rs b/src/main.rs index 638d773..12027d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,15 +32,20 @@ fn main() { player_controller.net_md_device.device_name().unwrap() ); - player_controller.play(); + println!("{:?}", player_controller.get_position()); + println!("{:?}", player_controller.go_to_time(0, 0, 2, 0, 0)); + let _ = player_controller.play(); + thread::sleep(Duration::from_secs(5)); + println!("{:?}", player_controller.get_position()); + println!("{:?}", player_controller.go_to_time(10, 0, 1, 15, 0)); + println!("{:?}", player_controller.get_position()); - println!("{:?}", player_controller.playback_status2()); - thread::sleep(Duration::from_secs(1)); - println!("{:?}", player_controller.playback_status2()); + thread::sleep(Duration::from_secs(10)); + println!("{:?}", player_controller.get_position()); - thread::sleep(Duration::from_secs(1)); + thread::sleep(Duration::from_secs(5)); - player_controller.stop(); + let _ = player_controller.stop(); /* let mut request: [u8; 19] = [0x00, 0x18, 0x06, 0x02, 0x20, 0x18, diff --git a/src/netmd/base.rs b/src/netmd/base.rs index 1443a2c..97decd0 100644 --- a/src/netmd/base.rs +++ b/src/netmd/base.rs @@ -93,6 +93,8 @@ pub struct NetMD { } impl NetMD { + const READ_REPLY_RETRY_INTERVAL: u32 = 10; + /// Creates a new `NetMD` struct pub fn new( device: DeviceHandle, @@ -141,37 +143,24 @@ impl NetMD { /// Poll the device to get either the result /// of the previous command, or the status - fn poll(&self, tries: usize) -> Result<(u16, [u8; 4]), Box> { + fn poll(&self) -> Result<(u16, [u8; 4]), Box> { // Create an array to store the result of the poll let mut poll_result = [0u8; 4]; - // Try until failure or `tries` reached - for i in 0..tries { - let _status = match self.device_connection.read_control( - STANDARD_RECV, - 0x01, - 0, - 0, - &mut poll_result, - DEFAULT_TIMEOUT, - ) { - Ok(size) => size, - Err(error) => return Err(error.into()), - }; + let _status = match self.device_connection.read_control( + STANDARD_RECV, + 0x01, + 0, + 0, + &mut poll_result, + DEFAULT_TIMEOUT, + ) { + Ok(size) => size, + Err(error) => return Err(error.into()), + }; - let length_bytes = [poll_result[2], poll_result[3]]; - - if poll_result[0] != 0 { - return Ok((u16::from_le_bytes(length_bytes), poll_result)); - } - - if i > 0 { - std::thread::sleep(std::time::Duration::from_secs(1)); - } - } - - // This should not contain anything let length_bytes = [poll_result[2], poll_result[3]]; + println!("Poll result: {}", u16::from_le_bytes(length_bytes)); Ok((u16::from_le_bytes(length_bytes), poll_result)) } @@ -190,7 +179,7 @@ impl NetMD { use_factory_command: bool, ) -> Result<(), Box> { //First poll to ensure the device is ready - match self.poll(1) { + match self.poll() { Ok(buffer) => match buffer.1[2] { 0 => 0, _ => return Err("Device not ready!".into()), @@ -216,21 +205,33 @@ impl NetMD { } } - pub fn read_reply(&self) -> Result, Box> { - self._read_reply(false) + pub fn read_reply(&self, override_length: Option) -> Result, Box> { + self._read_reply(false, override_length) } - pub fn read_factory_reply(&self) -> Result, Box> { - self._read_reply(true) + pub fn read_factory_reply(&self, override_length: Option) -> Result, Box> { + self._read_reply(true, override_length) } /// Poll to see if a message is ready, /// and if so, recieve it - fn _read_reply(&self, use_factory_command: bool) -> Result, Box> { - let poll_result = match self.poll(30) { - Ok(buffer) => buffer, - Err(error) => return Err(error), - }; + fn _read_reply(&self, use_factory_command: bool, override_length: Option) -> Result, Box> { + let mut length = self.poll()?.0; + + let mut current_attempt = 0; + while length == 0 { + let sleep_time = Self::READ_REPLY_RETRY_INTERVAL as u64 + * (u64::pow(2, current_attempt as u32 / 10) - 1); + + std::thread::sleep(std::time::Duration::from_millis(sleep_time)); + length = self.poll()?.0; + current_attempt += 1; + } + + match override_length { + Some(value) => length = value as u16, + None => () + } let request = match use_factory_command { false => 0x81, @@ -238,7 +239,7 @@ impl NetMD { }; // Create a buffer to fill with the result - let mut buf: Vec = vec![0; poll_result.0 as usize]; + let mut buf: Vec = vec![0; length as usize]; match self.device_connection.read_control( STANDARD_RECV, diff --git a/src/netmd/interface.rs b/src/netmd/interface.rs index 881ba8c..ba308b9 100644 --- a/src/netmd/interface.rs +++ b/src/netmd/interface.rs @@ -1,6 +1,7 @@ use crate::netmd::utils; use crate::NetMD; use std::error::Error; +use std::fmt; #[derive(Copy, Clone)] enum Action { @@ -188,6 +189,7 @@ impl NetMDInterface { u32::from_le_bytes(bytes) } + // TODO: Finish proper implementation fn disc_subunit_identifier(&self) -> Result> { self.change_descriptor_state( Descriptor::DiscSubunitIdentifier, @@ -271,6 +273,18 @@ impl NetMDInterface { Err("No supported media types found".into()) } + /* TODO: Finish implementation + fn factory(&self) -> Result> { + let device_name = self.net_md_device.device_name().expect("The device has no name"); + + let himd = device_name.contains("MZ-RH") || device_name.contains("MZ-NH"); + + self.disc_subunit_identifier()?; + + let constructor = + } + */ + fn net_md_level(&self) -> Result> { let result = self.disc_subunit_identifier()?; @@ -323,7 +337,7 @@ impl NetMDInterface { let mut data; while current_attempt < Self::MAX_INTERIM_READ_ATTEMPTS { - data = match self.net_md_device.read_reply() { + data = match self.net_md_device.read_reply(None) { Ok(reply) => reply, Err(error) => return Err(error.into()), }; @@ -396,6 +410,18 @@ impl NetMDInterface { Ok(()) } + fn acquire(&self) -> Result<(), Box> { + let mut query = vec![0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; + let reply = self.send_query(&mut query, false, false)?; + utils::check_result(reply, &[0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) + } + + fn release(&self) -> Result<(), Box> { + let mut query = vec![0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; + let reply = self.send_query(&mut query, false, false)?; + utils::check_result(reply, &[0xff, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]) + } + fn status(&self) -> Result, Box> { self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead); let mut query = vec![ @@ -411,7 +437,7 @@ impl NetMDInterface { Ok(res) } - pub fn is_disc_present(&self) -> Result> { + pub fn disc_present(&self) -> Result> { let status = self.status()?; println!("{:X?}", status); @@ -477,4 +503,105 @@ impl NetMDInterface { pub fn playback_status2(&self) -> Result, Box> { self.playback_status_query([0x88, 0x02], [0x88, 0x06]) } + + pub fn get_position(&self) -> Result<[u16; 5], Box> { + self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead); + + let mut query = vec![ + 0x18, 0x09, 0x80, 0x01, 0x04, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30, + 0x00, 0x03, 0x00, 0x30, 0x00, 0x02, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 + ]; + + let reply = match self.send_query(&mut query, false, false) { + Ok(result) => result, + Err(e) if e.to_string() == "Rejected" => Vec::new(), + Err(e) => return Err(e) + }; + + let track_number = u16::from_be_bytes([reply[35], reply[36]]); + + let hour = utils::byte_from_bcd(reply[37])?; + let minute = utils::byte_from_bcd(reply[38])?; + let second = utils::byte_from_bcd(reply[39])?; + let frame = utils::byte_from_bcd(reply[40])?; + + let final_result = [track_number, hour as u16, minute as u16, second as u16, frame as u16]; + + self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close); + + Ok(final_result) + } + + pub fn eject_disc(&self) -> Result<(), Box> { + let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00]; + let _reply = self.send_query(&mut query, false, false)?; + Ok(()) + } + + pub fn can_eject_disc(&self) -> Result> { + let mut query = vec![0x18, 0xc1, 0xff, 0x60, 0x00]; + match self.send_query(&mut query, true, false) { + Ok(_) => Ok(true), + Err(error) => Err(error) + } + } + + pub fn go_to_track(&self, track_number: u16) -> Result> { + let mut query = vec![0x18, 0x50, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, + 0b00, 0b00]; + + let bytes = track_number.to_le_bytes(); + + query[8] = bytes[1]; + query[9] = bytes[0]; + + let reply = self.send_query(&mut query, false, false)?; + + Ok(u16::from_be_bytes([reply[8], reply[9]])) + } + + pub fn go_to_time(&self, track_number: u16, hour: u8, minute: u8, second: u8, frame: u8) -> Result> { + let mut query = vec![0x18, 0x50, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0b00, 0b00, 0b00, 0b00, 0b00, 0b00]; + + let bytes = track_number.to_le_bytes(); + query[8] = bytes[1]; + query[9] = bytes[0]; + + query[10] = utils::bcd_from_byte(hour)?; + query[11] = utils::bcd_from_byte(minute)?; + query[12] = utils::bcd_from_byte(second)?; + query[13] = utils::bcd_from_byte(frame)?; + + let reply = self.send_query(&mut query, false, false)?; + + Ok(u16::from_be_bytes([reply[8], reply[9]])) + } + + fn _track_change(&self, direction: Track) -> Result<(), Box> { + let mut query = vec![0x18, 0x50, 0xff, 0x10, 0x00, 0x00, 0x00, 0x00, + 0b00, 0b00]; + + let direction_number = direction as u16; + let direction_bytes = direction_number.to_le_bytes(); + + query[8] = direction_bytes[1]; + query[9] = direction_bytes[0]; + + let _ = self.send_query(&mut query, false, false); + + Ok(()) + } + + pub fn next_track(&self) -> Result<(), Box> { + self._track_change(Track::Next) + } + + pub fn previous_track(&self) -> Result<(), Box> { + self._track_change(Track::Next) + } + + pub fn restart_track(&self) -> Result<(), Box> { + self._track_change(Track::Next) + } } diff --git a/src/netmd/utils.rs b/src/netmd/utils.rs index df19c34..c0467cf 100644 --- a/src/netmd/utils.rs +++ b/src/netmd/utils.rs @@ -6,3 +6,30 @@ pub fn check_result(result: Vec, expected: &[u8]) -> Result<(), Box Err("Response was not as expected!".into()), } } + +pub fn byte_from_bcd(byte: u8) -> Result> { + let upper = (byte & 0xF0) >> 4; + let lower = byte & 0x0F; + + if upper >= 10 { + return Err("Upper nybble out of range [0..9]".into()) + } + + if lower >= 10 { + return Err("Lower nybble out of range [0..9]".into()) + } + + Ok(upper * 10 + lower) +} + +pub fn bcd_from_byte(byte: u8) -> Result> { + let mut new_byte: u8 = 0; + + let upper = (byte / 10) << 4; + let lower = byte % 10; + + new_byte |= upper; + new_byte |= lower; + + Ok(new_byte) +}