Compare commits

..

No commits in common. "0a75b6a0134682e3979e151bb80e5f17cec9c290" and "dba4ba0df4ca86bd188f208fb2c7411a5b4d14e8" have entirely different histories.

7 changed files with 125 additions and 208 deletions

View file

@ -50,7 +50,6 @@ g2-unicode-jp = "0.4.1"
thiserror = "1.0.57"
phf = { version = "0.11.2", features = ["phf_macros", "macros"] }
byteorder = "1.5.0"
log = "0.4.22"
[target.'cfg(target_family = "wasm")'.dependencies]
gloo = { version = "0.11.0", features = ["futures", "worker"] }

View file

@ -5,13 +5,13 @@
//! [futures_lite](https://docs.rs/futures-lite/) with the `block_on` function.
//!
//! To use this library, first you need to get a device from [`cross_usb`] and
//! then open a [`netmd::NetMDContext`].
//! then open a [`NetMDContext`].
//!
//! ```no_run
//! # tokio_test::block_on(async {
//! use cross_usb::get_device;
//! use minidisc::netmd::base::DEVICE_IDS_CROSSUSB;
//! use minidisc::netmd::NetMDContext;
//! use minidisc::NetMDContext;
//!
//! // Get a device using the built-in list of descriptors for minidisc devices
//! let dev_descriptor = cross_usb::get_device(DEVICE_IDS_CROSSUSB.to_vec()).await
@ -28,3 +28,6 @@
//! ```
pub mod netmd;
#[doc(inline)]
pub use netmd::commands::NetMDContext;

View file

@ -117,12 +117,7 @@ pub enum NetMDError {
UsbError(#[from] UsbError),
}
/// A low-level USB connection to a NetMD device.
///
/// With this you can send raw commands to the device and recieve raw data.
///
/// For simple communication with a NetMD device, you most likely want the
/// higher level [`super::NetMDInterface`] or [`super::NetMDContext`] interfaces
/// A USB connection to a NetMD device
pub struct NetMD {
usb_interface: Interface,
model: DeviceId,
@ -207,17 +202,15 @@ impl NetMD {
Ok((length_bytes, poll_result))
}
/// Send a control message to the device (Raw bytes)
pub async fn send_command(&mut self, command: Vec<u8>) -> Result<(), NetMDError> {
self._send_command(command, false).await
}
/// Send a factory control message to the device (Raw bytes)
pub async fn send_factory_command(&mut self, command: Vec<u8>) -> Result<(), NetMDError> {
self._send_command(command, true).await
}
/// Send a control message to the device, can also send factory commands
/// Send a control message to the device
async fn _send_command(
&mut self,
command: Vec<u8>,

View file

@ -520,7 +520,7 @@ impl NetMDContext {
Ok((format, header))
}
async fn prepare_download(&mut self) -> Result<(), Box<dyn Error>> {
pub async fn prepare_download(&mut self) -> Result<(), Box<dyn Error>> {
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(
&self
.device_status()
@ -543,49 +543,13 @@ impl NetMDContext {
/// Start downloading an [`MDTrack`] to the device.
///
/// Progress is updated in the `progress_callback` closure.
///
/// # Downloading a track:
/// ```no_run
/// # tokio_test::block_on(async {
/// use minidisc::netmd::DEVICE_IDS_CROSSUSB;
/// use minidisc::netmd::NetMDContext;
/// use minidisc::netmd::encryption::new_thread_encryptor;
/// use minidisc::netmd::interface::{MDTrack, NetMDInterface};
///
/// // Get the minidisc device from cross_usb
/// let device = cross_usb::get_device(DEVICE_IDS_CROSSUSB.to_vec()).await.unwrap();
///
/// // Obtain a NetMDContext and acquire it
/// let mut context = NetMDContext::new(device).await.unwrap();
/// context.interface_mut().acquire().await.unwrap();
///
/// // Read in an audio file to a vec, for LP2 and LP4 this must be encoded properly
/// let track_contents: Vec<u8> =
/// std::fs::read("audio_file.wav")
/// .expect("Could not read track")[0x60..].to_vec();
///
/// // Construct the track
/// let track = MDTrack {
/// chunk_size: 0x400,
/// title: String::from("My Track Title"),
/// format: minidisc::netmd::interface::WireFormat::LP2,
/// full_width_title: None,
/// data: track_contents,
/// encrypt_packets_iterator: Box::new(new_thread_encryptor),
/// };
///
/// // Download it to the player!
/// context.download(
/// track,
/// |out_of: usize, done: usize| println!("Done {} / {}", done, out_of)
/// ).await.expect("Starting download failed");
/// # })
/// ```
pub async fn download<F: Fn(usize, usize)>(
pub async fn download<F>(
&mut self,
track: MDTrack,
progress_callback: F,
) -> Result<(u16, Vec<u8>, Vec<u8>), Box<dyn Error>>
where
F: Fn(usize, usize),
{
self.prepare_download().await?;
// Lock the interface by providing it to the session

View file

@ -8,7 +8,6 @@ use crate::netmd::utils::{
use cbc::cipher::block_padding::NoPadding;
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyInit, KeyIvInit};
use encoding_rs::SHIFT_JIS;
use log::debug;
use num_derive::FromPrimitive;
use rand::RngCore;
use std::collections::HashMap;
@ -20,7 +19,6 @@ use tokio::sync::mpsc::UnboundedReceiver;
use super::base::NetMD;
use super::utils::{cross_sleep, to_sjis};
/// An action to take on the player
#[derive(Copy, Clone)]
enum Action {
Play = 0x75,
@ -29,14 +27,12 @@ enum Action {
Rewind = 0x49,
}
/// Direction of playback, or restart track
pub enum Direction {
Previous = 0x0002,
Next = 0x8001,
Restart = 0x0001,
}
/// The format of the disc
#[derive(Debug, Clone, Copy, FromPrimitive, PartialEq, Eq)]
pub enum DiscFormat {
LP4 = 0,
@ -45,7 +41,6 @@ pub enum DiscFormat {
SPStereo = 6,
}
/// The format of the audio
#[derive(Clone, Hash, Eq, PartialEq, FromPrimitive)]
pub enum WireFormat {
Pcm = 0x00,
@ -74,7 +69,6 @@ impl WireFormat {
}
}
/// The encoding of the audio
#[derive(Debug, Clone, Copy)]
pub enum Encoding {
SP = 0x90,
@ -92,7 +86,6 @@ impl std::fmt::Display for Encoding {
}
}
/// The number of channels in the audio
#[derive(Debug, Clone, Copy)]
pub enum Channels {
Mono = 0x01,
@ -113,7 +106,6 @@ enum ChannelCount {
Stereo = 2,
}
/// The protected flag on a track
#[derive(Debug, Clone, Copy, FromPrimitive)]
pub enum TrackFlag {
Protected = 0x03,
@ -129,13 +121,11 @@ impl std::fmt::Display for TrackFlag {
}
}
/// The write protect flag on a disc
pub enum DiscFlag {
Writable = 0x10,
WriteProtected = 0x40,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
enum NetMDLevel {
Level1 = 0x20, // Network MD
@ -190,7 +180,6 @@ enum DescriptorAction {
Close = 0,
}
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
enum NetmdStatus {
// NetMD Protocol return status (first byte of request)
@ -210,8 +199,8 @@ enum NetmdStatus {
}
#[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[error("invalid status code: {}", 1)]
pub struct StatusError(u16);
#[error("invalid status code")]
pub struct StatusError;
impl TryFrom<u8> for NetmdStatus {
type Error = StatusError;
@ -230,7 +219,7 @@ impl TryFrom<u8> for NetmdStatus {
0x0c => Ok(NetmdStatus::Implemented),
0x0d => Ok(NetmdStatus::Changed),
0x0f => Ok(NetmdStatus::Interim),
code => Err(StatusError(code as u16)),
_ => Err(StatusError),
}
}
}
@ -243,7 +232,6 @@ struct MediaInfo {
supports_md_clip: u8,
}
/// An error when encrypting packets
#[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum EncryptionError {
#[error("supplied depth of {0} is invalid")]
@ -253,7 +241,6 @@ pub enum EncryptionError {
InvalidLength(&'static str, usize),
}
/// An error for any action in the interface
#[derive(Error, Debug, Eq, PartialEq, PartialOrd, Ord)]
pub enum InterfaceError {
#[error("could not parse data from a device")]
@ -333,9 +320,9 @@ impl NetMDInterface {
)
.await?;
let query = format_query("1809 00 ff00 0000 0000".to_string(), vec![])?;
let mut query = format_query("1809 00 ff00 0000 0000".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
@ -443,7 +430,7 @@ impl NetMDInterface {
query.push(0x00);
match self.send_query(&query, false, false).await {
match self.send_query(&mut query, false, false).await {
Ok(_) => Ok(()),
Err(err) => Err(err),
}
@ -452,7 +439,7 @@ impl NetMDInterface {
/// Send a query to the NetMD player
async fn send_query(
&mut self,
query: &Vec<u8>,
query: &mut Vec<u8>,
test: bool,
accept_interim: bool,
) -> Result<Vec<u8>, InterfaceError> {
@ -465,7 +452,7 @@ impl NetMDInterface {
async fn send_command(
&mut self,
query: &Vec<u8>,
query: &mut Vec<u8>,
test: bool,
) -> Result<(), InterfaceError> {
let status_byte = match test {
@ -476,7 +463,7 @@ impl NetMDInterface {
let mut new_query = Vec::new();
new_query.push(status_byte as u8);
new_query.extend_from_slice(&query);
new_query.append(query);
self.device.send_command(new_query).await?;
@ -491,7 +478,6 @@ impl NetMDInterface {
data = self.device.read_reply(None).await?;
let status = NetmdStatus::try_from(data[0])?;
debug!("Device status: {:?}", status);
match status {
NetmdStatus::NotImplemented => {
@ -524,12 +510,12 @@ impl NetMDInterface {
}
async fn playback_control(&mut self, action: Action) -> Result<(), InterfaceError> {
let query = format_query(
let mut query = format_query(
"18c3 ff %b 000000".to_string(),
vec![QueryValue::Number(action as i64)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "18c3 00 %b 000000".to_string())?;
@ -559,9 +545,9 @@ impl NetMDInterface {
//TODO: Implement fix for LAM-1
/// Stop playback
pub async fn stop(&mut self) -> Result<(), InterfaceError> {
let query = format_query("18c5 ff 00000000".to_string(), vec![])?;
let mut query = format_query("18c5 ff 00000000".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "18c5 00 00000000".to_string())?;
@ -569,8 +555,8 @@ impl NetMDInterface {
}
pub async fn acquire(&mut self) -> Result<(), InterfaceError> {
let query = format_query("ff 010c ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let mut query = format_query("ff 010c ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "ff 010c ffff ffff ffff ffff ffff ffff".to_string())?;
@ -578,9 +564,9 @@ impl NetMDInterface {
}
pub async fn release(&mut self) -> Result<(), InterfaceError> {
let query = format_query("ff 0100 ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
let mut query = format_query("ff 0100 ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "ff 0100 ffff ffff ffff ffff ffff ffff".to_string())?;
@ -594,12 +580,12 @@ impl NetMDInterface {
)
.await?;
let query = format_query(
let mut query = format_query(
"1809 8001 0230 8800 0030 8804 00 ff00 00000000".to_string(),
vec![],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
@ -631,12 +617,12 @@ impl NetMDInterface {
)
.await?;
let query = format_query(
let mut query = format_query(
"1809 8001 0330 8802 0030 8805 0030 8806 00 ff00 00000000".to_string(),
vec![],
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let result = scan_query(
reply,
@ -650,9 +636,7 @@ impl NetMDInterface {
.await?;
if operating_status.len() < 2 {
if !operating_status.is_empty() {
return Err(InterfaceError::InvalidStatus(StatusError(operating_status[0] as u16)));
}
return Err(InterfaceError::InvalidStatus(StatusError));
}
let operating_status_number =
@ -674,23 +658,20 @@ impl NetMDInterface {
)
.await?;
let query = format_query(
let mut query = format_query(
"1809 8001 0330 %w 0030 8805 0030 %w 00 ff00 00000000".to_string(),
vec![QueryValue::Number(p1 as i64), QueryValue::Number(p2 as i64)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
"1809 8001 0330 %?%? %?%? %?%? %?%? %?%? %? 1000 00%?0000 %x %?".to_string(),
)?;
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::Close
)
.await?;
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close)
.await?;
Ok(res[0].to_vec().unwrap())
}
@ -708,18 +689,21 @@ impl NetMDInterface {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
).await?;
)
.await?;
let query = format_query(
let mut query = format_query(
"1809 8001 0430 8802 0030 8805 0030 0003 0030 0002 00 ff00 00000000".to_string(),
vec![],
)
.unwrap();
//TODO: Ensure this is ok, we might want to do proper error handling
let reply = match self.send_query(&query, false, false).await {
Ok(d) => d,
Err(_) => return Ok([0u16; 5]),
let reply = match self.send_query(&mut query, false, false).await {
Ok(result) => result,
Err(e) => match e {
InterfaceError::Rejected(_) => Vec::new(),
_ => return Err(e),
},
};
let result = scan_query(reply, "1809 8001 0430 %?%? %?%? %?%? %?%? %?%? %?%? %?%? %? %?00 00%?0000 000b 0002 0007 00 %w %B %B %B %B".to_string())?;
@ -732,28 +716,26 @@ impl NetMDInterface {
result[4].to_i64().unwrap() as u16,
];
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::Close
).await?;
self.change_descriptor_state(&Descriptor::OperatingStatusBlock, &DescriptorAction::Close)
.await?;
Ok(final_result)
}
/// Eject the disc from the player if supported
pub async fn eject_disc(&mut self) -> Result<(), InterfaceError> {
let query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
let _reply = self.send_query(&query, false, false).await?;
let _reply = self.send_query(&mut query, false, false).await?;
Ok(())
}
/// Check if the machine has the capability to eject a disc
pub async fn can_eject_disc(&mut self) -> Result<bool, InterfaceError> {
let query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
match self.send_query(&query, true, false).await {
match self.send_query(&mut query, true, false).await {
Ok(_) => Ok(true),
Err(error) => Err(error),
}
@ -761,13 +743,13 @@ impl NetMDInterface {
/// Move the playback to a specific track
pub async fn go_to_track(&mut self, track_number: u16) -> Result<u16, InterfaceError> {
let query = format_query(
let mut query = format_query(
"1850 ff010000 0000 %w".to_string(),
vec![QueryValue::Number(track_number as i64)],
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1850 00010000 0000 %w".to_string())?;
@ -785,7 +767,7 @@ impl NetMDInterface {
second: u8,
frame: u8,
) -> Result<u16, InterfaceError> {
let query = format_query(
let mut query = format_query(
"1850 ff000000 0000 %w %B%B%B%B".to_string(),
vec![
QueryValue::Number(track_number as i64),
@ -797,7 +779,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1850 00000000 %?%? %w %B%B%B%B".to_string())?;
@ -806,15 +788,14 @@ impl NetMDInterface {
Ok(value as u16)
}
/// Change track in a [`Direction`]
pub async fn track_change(&mut self, direction: Direction) -> Result<(), InterfaceError> {
let query = format_query(
let mut query = format_query(
"1850 ff10 00000000 %w".to_string(),
vec![QueryValue::Number(direction as i64)],
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1850 0010 00000000 %?%?".to_string())?;
@ -823,22 +804,21 @@ impl NetMDInterface {
/// Erase the disc entirely
pub async fn erase_disc(&mut self) -> Result<(), InterfaceError> {
let query = format_query("1840 ff 0000".to_string(), vec![]).unwrap();
let reply = self.send_query(&query, false, false).await?;
let mut query = format_query("1840 ff 0000".to_string(), vec![]).unwrap();
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1840 00 0000".to_string())?;
Ok(())
}
// TODO: Ensure this is returning the correct value, it
// looks like it actually might be a 16 bit integer
/// Get the flags from a disc
pub async fn disc_flags(&mut self) -> Result<u8, InterfaceError> {
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead)
.await?;
let query = format_query("1806 01101000 ff00 0001000b".to_string(), vec![]).unwrap();
let mut query = format_query("1806 01101000 ff00 0001000b".to_string(), vec![]).unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1806 01101000 1000 0001000b %b".to_string()).unwrap();
@ -848,15 +828,15 @@ impl NetMDInterface {
Ok(res[0].to_i64().unwrap() as u8)
}
/// Get the number of tracks on the disc
/// The number of tracks on the disc
pub async fn track_count(&mut self) -> Result<u16, InterfaceError> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead)
.await?;
let query =
let mut query =
format_query("1806 02101001 3000 1000 ff00 00000000".to_string(), vec![]).unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
@ -890,7 +870,7 @@ impl NetMDInterface {
false => 0,
};
let query = format_query(
let mut query = format_query(
"1806 02201801 00%b 3000 0a00 ff00 %w%w".to_string(),
vec![
QueryValue::Number(wchar_value),
@ -900,7 +880,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
if remaining == 0 {
let res = scan_query(
@ -937,7 +917,7 @@ impl NetMDInterface {
Ok(res)
}
/// Gets the disc title without group information
/// Gets the disc title
pub async fn disc_title(&mut self, wchar: bool) -> Result<String, InterfaceError> {
let mut title = self.raw_disc_title(wchar).await?;
@ -1071,7 +1051,7 @@ impl NetMDInterface {
let mut track_titles: Vec<String> = vec![];
for i in tracks {
let query = format_query(
let mut query = format_query(
"1806 022018%b %w 3000 0a00 ff00 00000000".to_string(),
vec![
QueryValue::Number(wchar_value),
@ -1080,7 +1060,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
@ -1115,9 +1095,6 @@ impl NetMDInterface {
}
// Sets the title of the disc
//
// Caution: This does not respect groups. Use the functions available in
// NetMDContext to properly rename a disc.
pub async fn set_disc_title(&mut self, title: &str, wchar: bool) -> Result<(), InterfaceError> {
let current_title = self.raw_disc_title(wchar).await?;
if current_title == title {
@ -1150,7 +1127,7 @@ impl NetMDInterface {
.await?
}
let query = format_query(
let mut query = format_query(
"1807 02201801 00%b 3000 0a00 5000 %w 0000 %w %*".to_string(),
vec![
QueryValue::Number(wchar_value),
@ -1160,7 +1137,7 @@ impl NetMDInterface {
],
)?;
let _ = self.send_query(&query, false, false).await;
let _ = self.send_query(&mut query, false, false).await;
if self.device.vendor_id() == 0x04dd {
self.change_descriptor_state(&Descriptor::AudioUTOC1TD, &DescriptorAction::Close)
@ -1214,7 +1191,7 @@ impl NetMDInterface {
self.change_descriptor_state(&descriptor, &DescriptorAction::OpenWrite)
.await?;
let query = format_query(
let mut query = format_query(
"1807 022018%b %w 3000 0a00 5000 %w 0000 %w %*".to_string(),
vec![
QueryValue::Number(wchar_value),
@ -1224,7 +1201,7 @@ impl NetMDInterface {
QueryValue::Array(new_title),
],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let _ = scan_query(
reply,
@ -1238,19 +1215,19 @@ impl NetMDInterface {
/// Erases a track from the disc's UTOC
pub async fn erase_track(&mut self, track: u16) -> Result<(), InterfaceError> {
let query = format_query(
let mut query = format_query(
"1840 ff01 00 201001 %w".to_string(),
vec![QueryValue::Number(track as i64)],
)?;
let _result = self.send_query(&query, false, false).await;
let _result = self.send_query(&mut query, false, false).await;
Ok(())
}
/// Moves a track to another index on the disc
pub async fn move_track(&mut self, source: u16, dest: u16) -> Result<(), InterfaceError> {
let query = format_query(
let mut query = format_query(
"1843 ff00 00 201001 %w 201001 %w".to_string(),
vec![
QueryValue::Number(source as i64),
@ -1258,7 +1235,7 @@ impl NetMDInterface {
],
)?;
let _result = self.send_query(&query, false, false).await;
let _result = self.send_query(&mut query, false, false).await;
Ok(())
}
@ -1273,7 +1250,7 @@ impl NetMDInterface {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead)
.await?;
let query = format_query(
let mut query = format_query(
"1806 02201001 %w %w %w ff00 00000000".to_string(),
vec![
QueryValue::Number(track as i64),
@ -1282,7 +1259,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
"1806 02201001 %?%? %?%? %?%? 1000 00%?0000 %x".to_string(),
@ -1305,7 +1282,7 @@ impl NetMDInterface {
.await?;
for track in tracks {
let query = format_query(
let mut query = format_query(
"1806 02201001 %w %w %w ff00 00000000".to_string(),
vec![
QueryValue::Number(track as i64),
@ -1314,7 +1291,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(
reply,
@ -1381,11 +1358,11 @@ impl NetMDInterface {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead)
.await?;
let query = format_query(
let mut query = format_query(
"1806 01201001 %w ff00 00010008".to_string(),
vec![QueryValue::Number(track as i64)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1806 01201001 %?%? 10 00 00010008 %b".to_string())?;
@ -1400,8 +1377,8 @@ impl NetMDInterface {
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead)
.await?;
let query = format_query("1806 02101000 3080 0300 ff00 00000000".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let mut query = format_query("1806 02101000 3080 0300 ff00 00000000".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
// 8003 changed to %?03 - Panasonic returns 0803 instead. This byte's meaning is unknown
let res = scan_query(
@ -1433,12 +1410,12 @@ impl NetMDInterface {
)
.await?;
let query = format_query(
let mut query = format_query(
"1809 8001 0330 8801 0030 8805 0030 8807 00 ff00 00000000".to_string(),
vec![],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1809 8001 0330 8801 0030 8805 0030 8807 00 1000 000e0000 000c 8805 0008 80e0 0110 %b %b 4000".to_string())?;
@ -1456,12 +1433,12 @@ impl NetMDInterface {
track: u16,
progress_callback: Option<F>,
) -> Result<(DiscFormat, u16, Vec<u8>), InterfaceError> {
let query = format_query(
let mut query = format_query(
"1800 080046 f003010330 ff00 1001 %w".to_string(),
vec![QueryValue::Number((track + 1) as i64)],
)?;
let reply = self.send_query(&query, false, true).await?;
let reply = self.send_query(&mut query, false, true).await?;
let res = scan_query(
reply,
@ -1496,28 +1473,28 @@ impl NetMDInterface {
}
pub async fn disable_new_track_protection(&mut self, val: u16) -> Result<(), InterfaceError> {
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 2b ff %w".to_string(),
vec![QueryValue::Number(val as i64)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1800 080046 f0030103 2b 00 %?%?".to_string())?;
Ok(())
}
pub async fn enter_secure_session(&mut self) -> Result<(), InterfaceError> {
let query = format_query("1800 080046 f0030103 80 ff".to_string(), vec![])?;
let mut query = format_query("1800 080046 f0030103 80 ff".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1800 080046 f0030103 80 00".to_string())?;
Ok(())
}
pub async fn leave_secure_session(&mut self) -> Result<(), InterfaceError> {
let query = format_query("1800 080046 f0030103 81 ff".to_string(), vec![])?;
let mut query = format_query("1800 080046 f0030103 81 ff".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1800 080046 f0030103 81 00".to_string())?;
Ok(())
}
@ -1529,9 +1506,9 @@ impl NetMDInterface {
///
/// The leaf ID is a 8-byte constant
pub async fn leaf_id(&mut self) -> Result<[u8; 8], InterfaceError> {
let query = format_query("1800 080046 f0030103 11 ff".to_string(), vec![])?;
let mut query = format_query("1800 080046 f0030103 11 ff".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1800 080046 f0030103 11 00 %*".to_string())?;
Ok(res[0].to_vec().unwrap().try_into().unwrap())
@ -1553,7 +1530,7 @@ impl NetMDInterface {
let keychains = keychain.concat();
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 12 ff %w 0000 %w %d %d %d 00000000 %* %*".to_string(),
vec![
QueryValue::Number(databytes as i64),
@ -1566,7 +1543,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(
reply,
@ -1587,12 +1564,12 @@ impl NetMDInterface {
))?;
}
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 20 ff 000000 %*".to_string(),
vec![QueryValue::Array(hostnonce)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1800 080046 f0030103 20 %? 000000 %#".to_string())?;
@ -1600,9 +1577,9 @@ impl NetMDInterface {
}
pub async fn session_key_forget(&mut self) -> Result<(), InterfaceError> {
let query = format_query("1800 080046 f0030103 21 ff 000000".to_string(), vec![])?;
let mut query = format_query("1800 080046 f0030103 21 ff 000000".to_string(), vec![])?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let _ = scan_query(reply, "1800 080046 f0030103 21 00 000000".to_string())?;
Ok(())
@ -1638,12 +1615,12 @@ impl NetMDInterface {
.encrypt_padded_mut::<NoPadding>(message.as_mut_slice(), 32)
.unwrap();
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 22 ff 0000 %*".to_string(),
vec![QueryValue::Array(message)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1800 080046 f0030103 22 00 0000".to_string())?;
@ -1667,7 +1644,7 @@ impl NetMDInterface {
.encrypt_padded_mut::<NoPadding>(&mut message, 8)
.unwrap();
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 48 ff 00 1001 %w %*".to_string(),
vec![
QueryValue::Number(track_number as i64),
@ -1675,7 +1652,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
scan_query(reply, "1800 080046 f0030103 48 00 00 1001 %?%?".to_string())?;
@ -1683,7 +1660,7 @@ impl NetMDInterface {
}
#[allow(clippy::too_many_arguments)]
pub async fn send_track<F: Fn(usize, usize)>(
pub async fn send_track<F>(
&mut self,
wireformat: u8,
discformat: u8,
@ -1694,6 +1671,8 @@ impl NetMDInterface {
hex_session_key: &[u8],
progress_callback: F,
) -> Result<(u16, Vec<u8>, Vec<u8>), InterfaceError>
where
F: Fn(usize, usize),
{
if hex_session_key.len() != 8 {
return Err(EncryptionError::InvalidLength(
@ -1707,7 +1686,7 @@ impl NetMDInterface {
let total_bytes: usize = (pkt_size + 24) as usize; //framesizedict[wireformat] * frames + pktcount * 24;
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 28 ff 000100 1001 ffff 00 %b %b %d %d".to_string(),
vec![
QueryValue::Number(wireformat as i64),
@ -1716,7 +1695,7 @@ impl NetMDInterface {
QueryValue::Number(total_bytes as i64),
],
)?;
let mut reply = self.send_query(&query, false, true).await?;
let mut reply = self.send_query(&mut query, false, true).await?;
scan_query(
reply,
"1800 080046 f0030103 28 00 000100 1001 %?%? 00 %*".to_string(),
@ -1765,11 +1744,11 @@ impl NetMDInterface {
}
pub async fn track_uuid(&mut self, track: u16) -> Result<String, InterfaceError> {
let query = format_query(
let mut query = format_query(
"1800 080046 f0030103 23 ff 1001 %w".to_string(),
vec![QueryValue::Number(track as i64)],
)?;
let reply = self.send_query(&query, false, false).await?;
let reply = self.send_query(&mut query, false, false).await?;
let res = scan_query(reply, "1800 080046 f0030103 23 00 1001 %?%? %*".to_string())?;
@ -1777,8 +1756,8 @@ impl NetMDInterface {
}
pub async fn terminate(&mut self) -> Result<(), InterfaceError> {
let query = format_query("1800 080046 f0030103 2a ff00".to_string(), vec![])?;
self.send_query(&query, false, false).await?;
let mut query = format_query("1800 080046 f0030103 2a ff00".to_string(), vec![])?;
self.send_query(&mut query, false, false).await?;
Ok(())
}
@ -1789,7 +1768,7 @@ type DesCbcEnc = cbc::Encryptor<des::Des>;
type DesCbcDec = cbc::Decryptor<des::Des>;
type TDesCbcEnc = cbc::Encryptor<des::TdesEde3>;
pub(super) fn retailmac(key: &[u8], value: &[u8], iv: &[u8; 8]) -> Vec<u8> {
pub fn retailmac(key: &[u8], value: &[u8], iv: &[u8; 8]) -> Vec<u8> {
let mut subkey_a = [0u8; 8];
subkey_a.copy_from_slice(&key[0..8]);
@ -1815,13 +1794,13 @@ pub(super) fn retailmac(key: &[u8], value: &[u8], iv: &[u8; 8]) -> Vec<u8> {
end[..8].to_vec()
}
pub(super) struct EKBData {
pub struct EKBData {
chains: [[u8; 16]; 2],
depth: i32,
signature: [u8; 24],
}
pub(super) struct EKBOpenSource;
pub struct EKBOpenSource;
impl EKBOpenSource {
pub fn root_key(&self) -> [u8; 16] {
@ -1930,7 +1909,7 @@ impl MDTrack {
}
}
pub(super) struct MDSession<'a> {
pub struct MDSession<'a> {
pub md: &'a mut NetMDInterface,
pub ekb_object: EKBOpenSource,
pub hex_session_key: Option<Vec<u8>>,
@ -1969,12 +1948,14 @@ impl<'a> MDSession<'a> {
Ok(())
}
pub async fn download_track<F: Fn(usize, usize)>(
pub async fn download_track<F>(
&mut self,
mut track: MDTrack,
progress_callback: F,
disc_format: Option<DiscFormat>,
) -> Result<(u16, Vec<u8>, Vec<u8>), Box<dyn Error>>
where
F: Fn(usize, usize),
{
if self.hex_session_key.is_none() {
return Err("Cannot download a track using a non-init()'ed session!".into());

View file

@ -8,15 +8,3 @@ pub mod interface;
mod mappings;
mod query_utils;
mod utils;
#[doc(inline)]
pub use base::DEVICE_IDS_CROSSUSB;
#[doc(inline)]
pub use commands::NetMDContext;
#[doc(inline)]
pub use interface::NetMDInterface;
#[doc(inline)]
pub use base::NetMD;

View file

@ -90,16 +90,13 @@ pub enum QueryError {
#[error("unrecognized format character: `{0}`")]
UnrecognizedChar(char),
#[error("format and input mismatch at {index}: expected {expected:#04x}, got {actual:#04x} (format {format_string})")]
#[error("Format and input mismatch at {index}: expected {expected:#04x}, got {actual:#04x} (format {format_string})")]
InputMismatch {
index: usize,
expected: u8,
actual: u8,
format_string: String,
},
#[error("input data is empty")]
EmptyData,
}
/// Formats a query using a standard input to send to the player
@ -199,14 +196,6 @@ pub fn format_query(format: String, args: Vec<QueryValue>) -> Result<Vec<u8>, Qu
/// Scans a result using a standard input to recieve from the player
pub fn scan_query(query_result: Vec<u8>, format: String) -> Result<Vec<QueryValue>, QueryError> {
if DEBUG {
println!("RECV<<< F: {}", format);
}
if query_result.is_empty() {
return Err(QueryError::EmptyData)
}
let mut result: Vec<QueryValue> = Vec::new();
let initial_length = query_result.len();