Added more functions to interface, cleaned up base.rs

This commit is contained in:
G2-Games 2023-09-23 15:06:48 -05:00
parent 3980cfa189
commit 4a76d96341
5 changed files with 206 additions and 45 deletions

View file

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bcd-numbers = "1.0.11"
nofmt = "1.0.0" nofmt = "1.0.0"
once_cell = "1.18.0" once_cell = "1.18.0"
rusb = "0.9.3" rusb = "0.9.3"

View file

@ -32,15 +32,20 @@ fn main() {
player_controller.net_md_device.device_name().unwrap() 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(10));
thread::sleep(Duration::from_secs(1)); println!("{:?}", player_controller.get_position());
println!("{:?}", player_controller.playback_status2());
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, let mut request: [u8; 19] = [0x00, 0x18, 0x06, 0x02, 0x20, 0x18,

View file

@ -93,6 +93,8 @@ pub struct NetMD {
} }
impl NetMD { impl NetMD {
const READ_REPLY_RETRY_INTERVAL: u32 = 10;
/// Creates a new `NetMD` struct /// Creates a new `NetMD` struct
pub fn new( pub fn new(
device: DeviceHandle<GlobalContext>, device: DeviceHandle<GlobalContext>,
@ -141,37 +143,24 @@ impl NetMD {
/// Poll the device to get either the result /// Poll the device to get either the result
/// of the previous command, or the status /// of the previous command, or the status
fn poll(&self, tries: usize) -> Result<(u16, [u8; 4]), Box<dyn Error>> { fn poll(&self) -> Result<(u16, [u8; 4]), Box<dyn Error>> {
// Create an array to store the result of the poll // Create an array to store the result of the poll
let mut poll_result = [0u8; 4]; let mut poll_result = [0u8; 4];
// Try until failure or `tries` reached let _status = match self.device_connection.read_control(
for i in 0..tries { STANDARD_RECV,
let _status = match self.device_connection.read_control( 0x01,
STANDARD_RECV, 0,
0x01, 0,
0, &mut poll_result,
0, DEFAULT_TIMEOUT,
&mut poll_result, ) {
DEFAULT_TIMEOUT, Ok(size) => size,
) { Err(error) => return Err(error.into()),
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]]; 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)) Ok((u16::from_le_bytes(length_bytes), poll_result))
} }
@ -190,7 +179,7 @@ impl NetMD {
use_factory_command: bool, use_factory_command: bool,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
//First poll to ensure the device is ready //First poll to ensure the device is ready
match self.poll(1) { match self.poll() {
Ok(buffer) => match buffer.1[2] { Ok(buffer) => match buffer.1[2] {
0 => 0, 0 => 0,
_ => return Err("Device not ready!".into()), _ => return Err("Device not ready!".into()),
@ -216,21 +205,33 @@ impl NetMD {
} }
} }
pub fn read_reply(&self) -> Result<Vec<u8>, Box<dyn Error>> { pub fn read_reply(&self, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(false) self._read_reply(false, override_length)
} }
pub fn read_factory_reply(&self) -> Result<Vec<u8>, Box<dyn Error>> { pub fn read_factory_reply(&self, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(true) self._read_reply(true, override_length)
} }
/// Poll to see if a message is ready, /// Poll to see if a message is ready,
/// and if so, recieve it /// and if so, recieve it
fn _read_reply(&self, use_factory_command: bool) -> Result<Vec<u8>, Box<dyn Error>> { fn _read_reply(&self, use_factory_command: bool, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> {
let poll_result = match self.poll(30) { let mut length = self.poll()?.0;
Ok(buffer) => buffer,
Err(error) => return Err(error), 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 { let request = match use_factory_command {
false => 0x81, false => 0x81,
@ -238,7 +239,7 @@ impl NetMD {
}; };
// Create a buffer to fill with the result // Create a buffer to fill with the result
let mut buf: Vec<u8> = vec![0; poll_result.0 as usize]; let mut buf: Vec<u8> = vec![0; length as usize];
match self.device_connection.read_control( match self.device_connection.read_control(
STANDARD_RECV, STANDARD_RECV,

View file

@ -1,6 +1,7 @@
use crate::netmd::utils; use crate::netmd::utils;
use crate::NetMD; use crate::NetMD;
use std::error::Error; use std::error::Error;
use std::fmt;
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
enum Action { enum Action {
@ -188,6 +189,7 @@ impl NetMDInterface {
u32::from_le_bytes(bytes) u32::from_le_bytes(bytes)
} }
// TODO: Finish proper implementation
fn disc_subunit_identifier(&self) -> Result<NetMDLevel, Box<dyn Error>> { fn disc_subunit_identifier(&self) -> Result<NetMDLevel, Box<dyn Error>> {
self.change_descriptor_state( self.change_descriptor_state(
Descriptor::DiscSubunitIdentifier, Descriptor::DiscSubunitIdentifier,
@ -271,6 +273,18 @@ impl NetMDInterface {
Err("No supported media types found".into()) Err("No supported media types found".into())
} }
/* TODO: Finish implementation
fn factory(&self) -> Result<NetMDLevel, Box<dyn Error>> {
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<NetMDLevel, Box<dyn Error>> { fn net_md_level(&self) -> Result<NetMDLevel, Box<dyn Error>> {
let result = self.disc_subunit_identifier()?; let result = self.disc_subunit_identifier()?;
@ -323,7 +337,7 @@ impl NetMDInterface {
let mut data; let mut data;
while current_attempt < Self::MAX_INTERIM_READ_ATTEMPTS { 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, Ok(reply) => reply,
Err(error) => return Err(error.into()), Err(error) => return Err(error.into()),
}; };
@ -396,6 +410,18 @@ impl NetMDInterface {
Ok(()) Ok(())
} }
fn acquire(&self) -> Result<(), Box<dyn Error>> {
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<dyn Error>> {
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<Vec<u8>, Box<dyn Error>> { fn status(&self) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead); self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead);
let mut query = vec![ let mut query = vec![
@ -411,7 +437,7 @@ impl NetMDInterface {
Ok(res) Ok(res)
} }
pub fn is_disc_present(&self) -> Result<bool, Box<dyn Error>> { pub fn disc_present(&self) -> Result<bool, Box<dyn Error>> {
let status = self.status()?; let status = self.status()?;
println!("{:X?}", status); println!("{:X?}", status);
@ -477,4 +503,105 @@ impl NetMDInterface {
pub fn playback_status2(&self) -> Result<Vec<u8>, Box<dyn Error>> { pub fn playback_status2(&self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query([0x88, 0x02], [0x88, 0x06]) self.playback_status_query([0x88, 0x02], [0x88, 0x06])
} }
pub fn get_position(&self) -> Result<[u16; 5], Box<dyn Error>> {
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<dyn Error>> {
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<bool, Box<dyn Error>> {
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<u16, Box<dyn Error>> {
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<u16, Box<dyn Error>> {
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<dyn Error>> {
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<dyn Error>> {
self._track_change(Track::Next)
}
pub fn previous_track(&self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next)
}
pub fn restart_track(&self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next)
}
} }

View file

@ -6,3 +6,30 @@ pub fn check_result(result: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn Erro
false => Err("Response was not as expected!".into()), false => Err("Response was not as expected!".into()),
} }
} }
pub fn byte_from_bcd(byte: u8) -> Result<u8, Box<dyn Error>> {
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<u8, Box<dyn Error>> {
let mut new_byte: u8 = 0;
let upper = (byte / 10) << 4;
let lower = byte % 10;
new_byte |= upper;
new_byte |= lower;
Ok(new_byte)
}