mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-04-19 19:52:53 -05:00
Cleaned up some functions, implemeted read_bulk
This commit is contained in:
parent
ae22de0b03
commit
a55d1f1cbe
4 changed files with 151 additions and 55 deletions
|
@ -32,6 +32,10 @@ fn main() {
|
|||
|
||||
player_controller.play();
|
||||
|
||||
println!("{:?}", player_controller.playback_status2());
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
println!("{:?}", player_controller.playback_status2());
|
||||
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
|
||||
player_controller.stop();
|
||||
|
|
|
@ -10,6 +10,8 @@ const STANDARD_SEND: u8 =
|
|||
const STANDARD_RECV: u8 =
|
||||
rusb::request_type(Direction::In, RequestType::Vendor, Recipient::Interface);
|
||||
|
||||
pub const CHUNKSIZE: u32 = 0x10000;
|
||||
|
||||
// TODO: I think this sucks, figure out a better way
|
||||
pub static DEVICE_IDS: Lazy<Vec<DeviceId>> = Lazy::new(|| nofmt::pls!{
|
||||
Vec::from([
|
||||
|
@ -134,7 +136,7 @@ impl NetMD {
|
|||
|
||||
/// Poll the device to get either the result
|
||||
/// of the previous command, or the status
|
||||
fn poll(&self, tries: usize) -> Result<(usize, [u8; 4]), Box<dyn Error>> {
|
||||
fn poll(&self, tries: usize) -> Result<(u16, [u8; 4]), Box<dyn Error>> {
|
||||
// Create an array to store the result of the poll
|
||||
let mut poll_result = [0u8; 4];
|
||||
|
||||
|
@ -152,8 +154,10 @@ impl NetMD {
|
|||
Err(error) => return Err(error.into()),
|
||||
};
|
||||
|
||||
let length_bytes = [poll_result[2], poll_result[3]];
|
||||
|
||||
if poll_result[0] != 0 {
|
||||
return Ok((poll_result[2] as usize, poll_result));
|
||||
return Ok((u16::from_le_bytes(length_bytes), poll_result));
|
||||
}
|
||||
|
||||
if i > 0 {
|
||||
|
@ -161,7 +165,9 @@ impl NetMD {
|
|||
}
|
||||
}
|
||||
|
||||
Ok((poll_result[2] as usize, poll_result))
|
||||
// This should not contain anything
|
||||
let length_bytes = [poll_result[2], poll_result[3]];
|
||||
Ok((u16::from_le_bytes(length_bytes), poll_result))
|
||||
}
|
||||
|
||||
/// Send a control message to the device
|
||||
|
@ -179,14 +185,14 @@ impl NetMD {
|
|||
Err(error) => return Err(error),
|
||||
};
|
||||
|
||||
let _ = match use_factory_command {
|
||||
let request = match use_factory_command {
|
||||
false => 0x80,
|
||||
true => 0xff,
|
||||
};
|
||||
|
||||
match self.device_connection.write_control(
|
||||
STANDARD_SEND,
|
||||
0x80,
|
||||
request,
|
||||
0,
|
||||
0,
|
||||
&command,
|
||||
|
@ -211,7 +217,7 @@ impl NetMD {
|
|||
};
|
||||
|
||||
// Create a buffer to fill with the result
|
||||
let mut buf: [u8; 255] = [0; 255];
|
||||
let mut buf: Vec<u8> = vec![0; poll_result.0 as usize];
|
||||
|
||||
match self.device_connection.read_control(
|
||||
STANDARD_RECV,
|
||||
|
@ -221,27 +227,34 @@ impl NetMD {
|
|||
&mut buf,
|
||||
DEFAULT_TIMEOUT,
|
||||
) {
|
||||
Ok(_) => Ok(buf[0..poll_result.0].to_vec()),
|
||||
Ok(_) => Ok(buf),
|
||||
Err(error) => return Err(error.into()),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement these properly, they will NOT work as is
|
||||
pub fn read_bulk<const S: usize>(&self, chunksize: u32) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let result = self.read_bulk_to_array::<S>(chunksize)?;
|
||||
// Default chunksize should be 0x10000
|
||||
pub fn read_bulk(&self, length: u32, chunksize: u32) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let result = self.read_bulk_to_array(length, chunksize)?;
|
||||
|
||||
Ok(result.to_vec())
|
||||
}
|
||||
|
||||
pub fn read_bulk_to_array<const S: usize>(&self, chunksize: u32) -> Result<[u8; S], Box<dyn Error>> {
|
||||
let mut buffer: [u8; S] = [0u8; S];
|
||||
pub fn read_bulk_to_array(&self, length: u32, chunksize: u32) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let final_result: Vec<u8> = Vec::new();
|
||||
let mut done = 0;
|
||||
|
||||
self.device_connection.read_bulk(
|
||||
1,
|
||||
&mut buffer,
|
||||
DEFAULT_TIMEOUT
|
||||
)?;
|
||||
while done < length {
|
||||
let to_read = std::cmp::min(chunksize, length - done);
|
||||
let mut buffer: Vec<u8> = vec![0; to_read as usize];
|
||||
|
||||
Ok(buffer)
|
||||
done += self.device_connection.read_bulk(
|
||||
1,
|
||||
&mut buffer,
|
||||
DEFAULT_TIMEOUT
|
||||
)? as u32;
|
||||
|
||||
}
|
||||
|
||||
Ok(final_result)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ impl NetMDInterface {
|
|||
u32::from_le_bytes(bytes)
|
||||
}
|
||||
|
||||
fn get_disc_subunit_identifier(&self) -> Result<NetMDLevel, Box<dyn Error>> {
|
||||
fn disc_subunit_identifier(&self) -> Result<NetMDLevel, Box<dyn Error>> {
|
||||
self.change_descriptor_state(
|
||||
Descriptor::DiscSubunitIdentifier,
|
||||
DescriptorAction::OpenRead,
|
||||
|
@ -267,42 +267,10 @@ impl NetMDInterface {
|
|||
Err("No supported media types found".into())
|
||||
}
|
||||
|
||||
fn playback_control(&self, action: Action) -> Result<(), Box<dyn Error>> {
|
||||
let mut query = vec![0x18, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||
fn net_md_level(&self) -> Result<NetMDLevel, Box<dyn Error>> {
|
||||
let result = self.disc_subunit_identifier()?;
|
||||
|
||||
query[3] = action as u8;
|
||||
|
||||
let result = self.send_query(&mut query, false, false)?;
|
||||
|
||||
utils::check_result(result, &[0x18, 0xc5, 0x00, action as u8, 0x00, 0x00, 0x00])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn play(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Play)
|
||||
}
|
||||
|
||||
pub fn fast_forward(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::FastForward)
|
||||
}
|
||||
|
||||
pub fn rewind(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Rewind)
|
||||
}
|
||||
|
||||
pub fn pause(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Pause)
|
||||
}
|
||||
|
||||
pub fn stop(&self) -> Result<(), Box<dyn Error>> {
|
||||
let mut query = vec![0x18, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||
|
||||
let result = self.send_query(&mut query, false, false)?;
|
||||
|
||||
utils::check_result(result, &[0x18, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00])?;
|
||||
|
||||
Ok(())
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn change_descriptor_state(&self, descriptor: Descriptor, action: DescriptorAction) {
|
||||
|
@ -384,4 +352,115 @@ impl NetMDInterface {
|
|||
// This should NEVER happen unless the code is changed wrongly
|
||||
Err("The max retries is set to 0".into())
|
||||
}
|
||||
|
||||
fn playback_control(&self, action: Action) -> Result<(), Box<dyn Error>> {
|
||||
let mut query = vec![0x18, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||
|
||||
query[3] = action as u8;
|
||||
|
||||
let result = self.send_query(&mut query, false, false)?;
|
||||
|
||||
utils::check_result(result, &[0x18, 0xc5, 0x00, action as u8, 0x00, 0x00, 0x00])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn play(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Play)
|
||||
}
|
||||
|
||||
pub fn fast_forward(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::FastForward)
|
||||
}
|
||||
|
||||
pub fn rewind(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Rewind)
|
||||
}
|
||||
|
||||
pub fn pause(&self) -> Result<(), Box<dyn Error>> {
|
||||
self.playback_control(Action::Pause)
|
||||
}
|
||||
|
||||
pub fn stop(&self) -> Result<(), Box<dyn Error>> {
|
||||
let mut query = vec![0x18, 0xc5, 0xff, 0x00, 0x00, 0x00, 0x00];
|
||||
|
||||
let result = self.send_query(&mut query, false, false)?;
|
||||
|
||||
utils::check_result(result, &[0x18, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn status(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead);
|
||||
let mut query = vec![0x18, 0x09, 0x80, 0x01, 0x02, 0x30, 0x88, 0x00, 0x00, 0x30, 0x88, 0x04, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00];
|
||||
let response = self.send_query(&mut query, false, false)?;
|
||||
|
||||
let res = response[22..].to_vec();
|
||||
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close);
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn is_disc_present(&self) -> Result<bool, Box<dyn Error>> {
|
||||
let status = self.status()?;
|
||||
|
||||
println!("{:X?}", status);
|
||||
|
||||
Ok(status[4] == 0x40)
|
||||
}
|
||||
|
||||
fn full_operating_status(&self) -> Result<(u8, u16), Box<dyn Error>> {
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead);
|
||||
let mut query = vec![0x18, 0x09, 0x80, 0x01, 0x03, 0x30, 0x88, 0x02, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30, 0x88, 0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00];
|
||||
let response = self.send_query(&mut query, false, false)?;
|
||||
|
||||
let operating_status = response[27..].to_vec();
|
||||
let status_mode = response[20];
|
||||
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close);
|
||||
|
||||
if operating_status.len() < 2 {
|
||||
return Err("Unparsable operating system".into())
|
||||
}
|
||||
|
||||
let status_bytes = [operating_status[0], operating_status[1]];
|
||||
|
||||
let operating_status_number = u16::from_le_bytes(status_bytes);
|
||||
|
||||
Ok((status_mode, operating_status_number))
|
||||
}
|
||||
|
||||
fn operating_status(&self) -> Result<u16, Box<dyn Error>> {
|
||||
let status = self.full_operating_status()?.1;
|
||||
|
||||
Ok(status)
|
||||
}
|
||||
|
||||
fn playback_status_query(&self, p1: [u8; 2], p2: [u8; 2]) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::OpenRead);
|
||||
let mut query = vec![0x18, 0x09, 0x80, 0x01, 0x03, 0x30, 0x00, 0x00, 0x00, 0x30, 0x88, 0x05, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00];
|
||||
|
||||
query[6] = p1[0];
|
||||
query[7] = p1[1];
|
||||
query[14] = p2[0];
|
||||
query[15] = p2[1];
|
||||
|
||||
let response = self.send_query(&mut query, false, false)?;
|
||||
|
||||
let playback_status = response[24..].to_vec();
|
||||
|
||||
self.change_descriptor_state(Descriptor::OperatingStatusBlock, DescriptorAction::Close);
|
||||
|
||||
Ok(playback_status)
|
||||
}
|
||||
|
||||
pub fn playback_status1(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
self.playback_status_query([0x88, 0x01], [0x88, 0x07])
|
||||
}
|
||||
|
||||
pub fn playback_status2(&self) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
self.playback_status_query([0x88, 0x02], [0x88, 0x06])
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,6 @@ use std::error::Error;
|
|||
pub fn check_result(result: Vec<u8>, expected: &[u8]) -> Result<(), Box<dyn Error>> {
|
||||
match result.as_slice().eq(expected) {
|
||||
true => Ok(()),
|
||||
false => Err("Response was not expected!".into()),
|
||||
false => Err("Response was not as expected!".into()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue