Compare commits

..

No commits in common. "9dce1e328e5f82a53eed0002971d8e8ebd1145d1" and "d0e42076d8badcdf8210f5cc92a32f1db9836281" have entirely different histories.

10 changed files with 532 additions and 666 deletions

View file

@ -9,10 +9,8 @@ authors = ["G2 <g2@g2games.dev>"]
license = "AGPL-3.0"
[dependencies]
futures = "0.3.30"
hex = "0.4.3"
nusb = "0.1.4"
tokio = { version = "1.35.1", features = ["full"] }
translit = "0.5.0"
[dependencies.minidisc-rs]

View file

@ -25,9 +25,7 @@ regex = "1.10.2"
lazy_static = "1.4.0"
nusb = "0.1.4"
futures-lite = "2.2.0"
num-derive = "0.3.3"
num-traits = "0.2.14"
rand = "0.8.5"
[lib]
crate-type = ["cdylib", "rlib"]

View file

@ -4,10 +4,13 @@ use std::error::Error;
use std::time::Duration;
// USB stuff
use nusb::transfer::{Control, ControlIn, ControlOut, ControlType, Recipient, RequestBuffer};
use nusb::transfer::{Control, ControlType, Recipient, RequestBuffer};
use nusb::{Device, DeviceInfo, Interface};
use futures_lite::future::block_on;
const DEFAULT_TIMEOUT: Duration = Duration::new(10000, 0);
const BULK_WRITE_ENDPOINT: u8 = 0x02;
const BULK_READ_ENDPOINT: u8 = 0x81;
@ -95,7 +98,7 @@ impl NetMD {
const READ_REPLY_RETRY_INTERVAL: u32 = 10;
/// Creates a new interface to a NetMD device
pub async fn new(device_info: &DeviceInfo) -> Result<Self, Box<dyn Error>> {
pub fn new(device_info: &DeviceInfo) -> Result<Self, Box<dyn Error>> {
let mut model = DeviceId {
vendor_id: device_info.vendor_id(),
product_id: device_info.product_id(),
@ -128,67 +131,61 @@ impl NetMD {
}
/// Gets the device name, this is limited to the devices in the list
pub async fn device_name(&self) -> &Option<String> {
pub fn device_name(&self) -> &Option<String> {
&self.model.name
}
/// Gets the vendor id
pub async fn vendor_id(&self) -> &u16 {
pub fn vendor_id(&self) -> &u16 {
&self.model.vendor_id
}
/// Gets the product id
pub async fn product_id(&self) -> &u16 {
pub fn product_id(&self) -> &u16 {
&self.model.product_id
}
/// Poll the device to get either the result
/// of the previous command, or the status
pub async fn poll(&mut self) -> Result<(u16, [u8; 4]), Box<dyn Error>> {
pub fn poll(&mut self) -> Result<(u16, [u8; 4]), Box<dyn Error>> {
// Create an array to store the result of the poll
let poll_result = match self
.usb_interface
.control_in(ControlIn {
let mut poll_result = [0u8; 4];
let _status = match self.usb_interface.control_in_blocking(
Control {
control_type: ControlType::Vendor,
recipient: Recipient::Interface,
request: 0x01,
value: 0,
index: 0,
length: 4,
})
.await
.into_result()
{
},
&mut poll_result,
DEFAULT_TIMEOUT,
) {
Ok(size) => size,
Err(error) => return Err(error.into()),
};
let length_bytes = u16::from_le_bytes([poll_result[2], poll_result[3]]);
let poll_result: [u8; 4] = match poll_result.try_into() {
Ok(val) => val,
Err(_) => return Err("could not convert result".into()),
};
Ok((length_bytes, poll_result))
let length_bytes = [poll_result[2], poll_result[3]];
Ok((u16::from_le_bytes(length_bytes), poll_result))
}
pub async fn send_command(&mut self, command: Vec<u8>) -> Result<(), Box<dyn Error>> {
self._send_command(command, false).await
pub fn send_command(&mut self, command: Vec<u8>) -> Result<(), Box<dyn Error>> {
self._send_command(command, false)
}
pub async fn send_factory_command(&mut self, command: Vec<u8>) -> Result<(), Box<dyn Error>> {
self._send_command(command, true).await
pub fn send_factory_command(&mut self, command: Vec<u8>) -> Result<(), Box<dyn Error>> {
self._send_command(command, true)
}
/// Send a control message to the device
async fn _send_command(
fn _send_command(
&mut self,
command: Vec<u8>,
use_factory_command: bool,
) -> Result<(), Box<dyn Error>> {
// First poll to ensure the device is ready
match self.poll().await {
match self.poll() {
Ok(buffer) => match buffer.1[2] {
0 => 0,
_ => return Err("Device not ready!".into()),
@ -201,54 +198,49 @@ impl NetMD {
true => 0xff,
};
match self
.usb_interface
.control_out(ControlOut {
match self.usb_interface.control_out_blocking(
Control {
control_type: ControlType::Vendor,
recipient: Recipient::Interface,
request,
value: 0,
index: 0,
data: &command,
})
.await
.into_result()
{
},
&command,
DEFAULT_TIMEOUT,
) {
Ok(_) => Ok(()),
Err(error) => Err(error.into()),
}
}
pub async fn read_reply(
pub fn read_reply(&mut self, override_length: Option<i32>) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(false, override_length)
}
pub fn read_factory_reply(
&mut self,
override_length: Option<i32>,
) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(false, override_length).await
self._read_reply(true, override_length)
}
pub async fn read_factory_reply(
&mut self,
override_length: Option<i32>,
) -> Result<Vec<u8>, Box<dyn Error>> {
self._read_reply(true, override_length).await
}
/// Poll to see if a message is ready, and once it is, retrieve it
async fn _read_reply(
/// Poll to see if a message is ready,
/// and if so, recieve it
fn _read_reply(
&mut self,
use_factory_command: bool,
override_length: Option<i32>,
) -> Result<Vec<u8>, Box<dyn Error>> {
let mut length = self.poll().await?.0;
let mut length = self.poll()?.0;
let mut current_attempt = 0;
while length == 0 {
// Back off while trying again
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().await?.0;
length = self.poll()?.0;
current_attempt += 1;
}
@ -262,35 +254,38 @@ impl NetMD {
};
// Create a buffer to fill with the result
let reply = self
.usb_interface
.control_in(ControlIn {
let mut buf: Vec<u8> = vec![0; length as usize];
// Create a buffer to fill with the result
match self.usb_interface.control_in_blocking(
Control {
control_type: ControlType::Vendor,
recipient: Recipient::Interface,
request,
value: 0,
index: 0,
length,
})
.await
.into_result()?;
Ok(reply)
},
&mut buf,
DEFAULT_TIMEOUT,
) {
Ok(_) => Ok(buf),
Err(error) => Err(error.into()),
}
}
// Default chunksize should be 0x10000
// TODO: Make these Async eventually
pub async fn read_bulk(
pub fn read_bulk(
&mut self,
length: usize,
chunksize: usize,
) -> Result<Vec<u8>, Box<dyn Error>> {
let result = self.read_bulk_to_array(length, chunksize).await?;
let result = self.read_bulk_to_array(length, chunksize)?;
Ok(result)
}
pub async fn read_bulk_to_array(
pub fn read_bulk_to_array(
&mut self,
length: usize,
chunksize: usize,
@ -303,10 +298,7 @@ impl NetMD {
done -= to_read;
let buffer = RequestBuffer::new(to_read);
let res = match self
.usb_interface
.bulk_in(BULK_READ_ENDPOINT, buffer)
.await
let res = match block_on(self.usb_interface.bulk_in(BULK_READ_ENDPOINT, buffer))
.into_result()
{
Ok(result) => result,
@ -319,12 +311,11 @@ impl NetMD {
Ok(final_result)
}
pub async fn write_bulk(&mut self, data: Vec<u8>) -> Result<usize, Box<dyn Error>> {
Ok(self
.usb_interface
.bulk_out(BULK_WRITE_ENDPOINT, data)
.await
pub fn write_bulk(&mut self, data: Vec<u8>) -> Result<usize, Box<dyn Error>> {
Ok(
block_on(self.usb_interface.bulk_out(BULK_WRITE_ENDPOINT, data))
.into_result()?
.actual_length())
.actual_length(),
)
}
}

View file

@ -1,77 +0,0 @@
use std::{error::Error, thread::sleep, time::Duration};
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use super::interface::{NetMDInterface, MDTrack};
#[derive(FromPrimitive)]
#[derive(PartialEq)]
pub enum OperatingStatus{
Ready = 50687,
Playing = 50037,
Paused = 50045,
FastForward = 49983,
Rewind = 49999,
ReadingTOC = 65315,
NoDisc = 65296,
DiscBlank = 65535,
ReadyForTransfer = 65319,
}
pub struct Time {
minute: u16,
second: u16,
frame: u16,
}
pub struct DeviceStatus {
disc_present: bool,
state: Option<OperatingStatus>,
track: u8,
time: Time,
}
pub async fn device_status(interface: &mut NetMDInterface) -> Result<DeviceStatus, Box<dyn Error>> {
let status = interface.status().await?;
let playback_status = interface.playback_status2().await?;
let b1: u16 = playback_status[4] as u16;
let b2: u16 = playback_status[5] as u16;
let position = interface.position().await?;
let operating_status = b1 << 8 | b2;
let track = position[0] as u8;
let disc_present = status[4] != 0x80;
let mut state: Option<OperatingStatus> = FromPrimitive::from_u16(operating_status);
if state == Some(OperatingStatus::Playing) && !disc_present {
state = Some(OperatingStatus::Ready);
}
let time = Time{
minute: position[2],
second: position[3],
frame: position[4],
};
Ok(DeviceStatus { disc_present, state, track, time })
}
pub async fn prepare_download(interface: &mut NetMDInterface) -> Result<(), Box<dyn Error>>{
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(&device_status(interface).await?.state.or(Some(OperatingStatus::NoDisc)).unwrap()) {
sleep(Duration::from_millis(200));
}
let _ = interface.session_key_forget();
let _ = interface.leave_secure_session();
interface.acquire().await?;
let _ = interface.disable_new_track_protection(1);
Ok(())
}
pub async fn download(interface: &mut NetMDInterface, track: MDTrack) -> Result<(), Box<dyn Error>>{
prepare_download(interface).await?;
Ok(())
}

View file

@ -7,7 +7,6 @@ use crate::netmd::utils::{
use encoding_rs::*;
use hex;
use magic_crypt::{new_magic_crypt, MagicCrypt, MagicCryptTrait, SecureBit};
use rand::RngCore;
use std::collections::HashMap;
use std::error::Error;
@ -38,7 +37,7 @@ pub enum DiscFormat {
}
#[derive(Clone, Hash, Eq, PartialEq)]
pub enum WireFormat {
enum WireFormat {
Pcm = 0x00,
L105kbps = 0x90,
LP2 = 0x94,
@ -203,8 +202,8 @@ impl NetMDInterface {
const MAX_INTERIM_READ_ATTEMPTS: u8 = 4;
const INTERIM_RESPONSE_RETRY_INTERVAL: u32 = 100;
pub async fn new(device: &nusb::DeviceInfo) -> Result<Self, Box<dyn Error>> {
let net_md_device = base::NetMD::new(device).await?;
pub fn new(device: &nusb::DeviceInfo) -> Result<Self, Box<dyn Error>> {
let net_md_device = base::NetMD::new(device)?;
Ok(NetMDInterface { net_md_device })
}
@ -219,7 +218,7 @@ impl NetMDInterface {
}
// TODO: Finish proper implementation
async fn disc_subunit_identifier(&mut self) -> Result<NetMDLevel, Box<dyn Error>> {
fn disc_subunit_identifier(&mut self) -> Result<NetMDLevel, Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::DiscSubunitIdentifier,
&DescriptorAction::OpenRead,
@ -227,7 +226,7 @@ impl NetMDInterface {
let mut query = format_query("1809 00 ff00 0000 0000".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -315,8 +314,8 @@ impl NetMDInterface {
}
*/
async fn net_md_level(&mut self) -> Result<NetMDLevel, Box<dyn Error>> {
let result = self.disc_subunit_identifier().await?;
fn net_md_level(&mut self) -> Result<NetMDLevel, Box<dyn Error>> {
let result = self.disc_subunit_identifier()?;
Ok(result)
}
@ -334,24 +333,20 @@ impl NetMDInterface {
}
/// Send a query to the NetMD player
async fn send_query(
fn send_query(
&mut self,
query: &mut Vec<u8>,
test: bool,
accept_interim: bool,
) -> Result<Vec<u8>, Box<dyn Error>> {
self.send_command(query, test).await?;
self.send_command(query, test)?;
let result = self.read_reply(accept_interim).await?;
let result = self.read_reply(accept_interim)?;
Ok(result)
}
async fn send_command(
&mut self,
query: &mut Vec<u8>,
test: bool,
) -> Result<(), Box<dyn Error>> {
fn send_command(&mut self, query: &mut Vec<u8>, test: bool) -> Result<(), Box<dyn Error>> {
let status_byte = match test {
true => Status::GeneralInquiry,
false => Status::Control,
@ -362,17 +357,17 @@ impl NetMDInterface {
new_query.push(status_byte as u8);
new_query.append(query);
self.net_md_device.send_command(new_query).await?;
self.net_md_device.send_command(new_query)?;
Ok(())
}
async fn read_reply(&mut self, accept_interim: bool) -> Result<Vec<u8>, Box<dyn Error>> {
fn read_reply(&mut self, accept_interim: bool) -> Result<Vec<u8>, Box<dyn Error>> {
let mut current_attempt = 0;
let mut data;
while current_attempt < Self::MAX_INTERIM_READ_ATTEMPTS {
data = match self.net_md_device.read_reply(None).await {
data = match self.net_md_device.read_reply(None) {
Ok(reply) => reply,
Err(error) => return Err(error),
};
@ -407,66 +402,66 @@ impl NetMDInterface {
Err("The max retries is set to 0".into())
}
async fn playback_control(&mut self, action: Action) -> Result<(), Box<dyn Error>> {
fn playback_control(&mut self, action: Action) -> Result<(), Box<dyn Error>> {
let mut query = format_query(
"18c3 00 %b 000000".to_string(),
vec![QueryValue::Number(action as i64)],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "18c3 00 %b 000000".to_string())?;
Ok(())
}
pub async fn play(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Play).await
pub fn play(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Play)
}
pub async fn fast_forward(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::FastForward).await
pub fn fast_forward(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::FastForward)
}
pub async fn rewind(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Rewind).await
pub fn rewind(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Rewind)
}
pub async fn pause(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Pause).await
pub fn pause(&mut self) -> Result<(), Box<dyn Error>> {
self.playback_control(Action::Pause)
}
//TODO: Implement fix for LAM-1
pub async fn stop(&mut self) -> Result<(), Box<dyn Error>> {
pub fn stop(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("18c5 ff 00000000".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "18c5 00 00000000".to_string())?;
Ok(())
}
pub async fn acquire(&mut self) -> Result<(), Box<dyn Error>> {
fn acquire(&mut self) -> Result<(), Box<dyn Error>> {
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?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "ff 010c ffff ffff ffff ffff ffff ffff".to_string())?;
Ok(())
}
async fn release(&mut self) -> Result<(), Box<dyn Error>> {
fn release(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("ff 0100 ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "ff 0100 ffff ffff ffff ffff ffff ffff".to_string())?;
Ok(())
}
pub async fn status(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn status(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
@ -477,7 +472,7 @@ impl NetMDInterface {
vec![],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -491,15 +486,15 @@ impl NetMDInterface {
Ok(final_array)
}
pub async fn disc_present(&mut self) -> Result<bool, Box<dyn Error>> {
let status = self.status().await?;
pub fn disc_present(&mut self) -> Result<bool, Box<dyn Error>> {
let status = self.status()?;
println!("{:X?}", status);
Ok(status[4] == 0x40)
}
async fn full_operating_status(&mut self) -> Result<(u8, u16), Box<dyn Error>> {
fn full_operating_status(&mut self) -> Result<(u8, u16), Box<dyn Error>> {
// WARNING: Does not work for all devices. See https://github.com/cybercase/webminidisc/issues/21
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
@ -510,7 +505,7 @@ impl NetMDInterface {
vec![],
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let result = scan_query(
reply,
@ -532,13 +527,13 @@ impl NetMDInterface {
Ok((status_mode, operating_status_number))
}
pub async fn operating_status(&mut self) -> Result<u16, Box<dyn Error>> {
let status = self.full_operating_status().await?.1;
pub fn operating_status(&mut self) -> Result<u16, Box<dyn Error>> {
let status = self.full_operating_status()?.1;
Ok(status)
}
async fn playback_status_query(&mut self, p1: u32, p2: u32) -> Result<Vec<u8>, Box<dyn Error>> {
fn playback_status_query(&mut self, p1: u32, p2: u32) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
@ -549,7 +544,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -561,15 +556,15 @@ impl NetMDInterface {
Ok(res.unwrap()[0].to_vec().unwrap())
}
pub async fn playback_status1(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query(0x8801, 0x8807).await
pub fn playback_status1(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query(0x8801, 0x8807)
}
pub async fn playback_status2(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query(0x8802, 0x8806).await
pub fn playback_status2(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.playback_status_query(0x8802, 0x8806)
}
pub async fn position(&mut self) -> Result<[u16; 5], Box<dyn Error>> {
pub fn position(&mut self) -> Result<[u16; 5], Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
@ -581,7 +576,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = match self.send_query(&mut query, false, false).await {
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),
@ -602,31 +597,31 @@ impl NetMDInterface {
Ok(final_result)
}
pub async fn eject_disc(&mut self) -> Result<(), Box<dyn Error>> {
pub fn eject_disc(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
let _reply = self.send_query(&mut query, false, false).await?;
let _reply = self.send_query(&mut query, false, false)?;
Ok(())
}
pub async fn can_eject_disc(&mut self) -> Result<bool, Box<dyn Error>> {
pub fn can_eject_disc(&mut self) -> Result<bool, Box<dyn Error>> {
let mut query = format_query("18c1 ff 6000".to_string(), vec![]).unwrap();
match self.send_query(&mut query, true, false).await {
match self.send_query(&mut query, true, false) {
Ok(_) => Ok(true),
Err(error) => Err(error),
}
}
/* Track control */
pub async fn go_to_track(&mut self, track_number: u16) -> Result<u16, Box<dyn Error>> {
pub fn go_to_track(&mut self, track_number: u16) -> Result<u16, Box<dyn Error>> {
let mut query = format_query(
"1850 ff010000 0000 %w".to_string(),
vec![QueryValue::Number(track_number as i64)],
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1850 00010000 0000 %w".to_string())?;
@ -635,7 +630,7 @@ impl NetMDInterface {
Ok(value as u16)
}
pub async fn go_to_time(
pub fn go_to_time(
&mut self,
track_number: u16,
hour: u8,
@ -655,7 +650,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1850 00000000 %?%? %w %B%B%B%B".to_string())?;
@ -664,14 +659,14 @@ impl NetMDInterface {
Ok(value as u16)
}
async fn track_change(&mut self, direction: Track) -> Result<(), Box<dyn Error>> {
fn _track_change(&mut self, direction: Track) -> Result<(), Box<dyn Error>> {
let mut query = format_query(
"1850 ff10 00000000 %w".to_string(),
vec![QueryValue::Number(direction as i64)],
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1850 0010 00000000 %?%?".to_string())?;
@ -679,35 +674,35 @@ impl NetMDInterface {
}
/// Change to the next track (skip forward)
pub async fn next_track(&mut self) -> Result<(), Box<dyn Error>> {
self.track_change(Track::Next).await
pub fn next_track(&mut self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next)
}
/// Change to the next track (skip back)
pub async fn previous_track(&mut self) -> Result<(), Box<dyn Error>> {
self.track_change(Track::Next).await
pub fn previous_track(&mut self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next)
}
/// Change to the next track (skip to beginning of track)
pub async fn restart_track(&mut self) -> Result<(), Box<dyn Error>> {
self.track_change(Track::Next).await
pub fn restart_track(&mut self) -> Result<(), Box<dyn Error>> {
self._track_change(Track::Next)
}
/* Content access and control */
pub async fn erase_disc(&mut self) -> Result<(), Box<dyn Error>> {
pub fn erase_disc(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("1840 ff 0000".to_string(), vec![]).unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
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
pub async fn disc_flags(&mut self) -> Result<u8, Box<dyn Error>> {
pub fn disc_flags(&mut self) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead);
let mut query = format_query("1806 01101000 ff00 0001000b".to_string(), vec![]).unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1806 01101000 1000 0001000b %b".to_string()).unwrap();
@ -717,13 +712,13 @@ impl NetMDInterface {
}
/// The number of tracks on the disc
pub async fn track_count(&mut self) -> Result<u16, Box<dyn Error>> {
pub fn track_count(&mut self) -> Result<u16, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead);
let mut query =
format_query("1806 02101001 3000 1000 ff00 00000000".to_string(), vec![]).unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -736,7 +731,7 @@ impl NetMDInterface {
Ok(res[0].to_i64().unwrap() as u16)
}
async fn raw_disc_title(&mut self, wchar: bool) -> Result<String, Box<dyn Error>> {
fn _disc_title(&mut self, wchar: bool) -> Result<String, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead);
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::OpenRead);
@ -763,7 +758,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
if remaining == 0 {
let res = scan_query(
@ -799,8 +794,8 @@ impl NetMDInterface {
}
/// Gets the disc title
pub async fn disc_title(&mut self, wchar: bool) -> Result<String, Box<dyn Error>> {
let mut title = self.raw_disc_title(wchar).await?;
pub fn disc_title(&mut self, wchar: bool) -> Result<String, Box<dyn Error>> {
let mut title = self._disc_title(wchar)?;
let delim = match wchar {
true => "",
@ -825,16 +820,16 @@ impl NetMDInterface {
}
/// Gets all groups on the disc
pub async fn track_group_list(
pub fn track_group_list(
&mut self,
) -> Result<Vec<(Option<String>, Option<String>, Vec<u16>)>, Box<dyn Error>> {
let raw_title = self.raw_disc_title(false).await?;
let raw_title = self._disc_title(false)?;
let group_list = raw_title.split("//");
let mut track_dict: HashMap<u16, (String, u16)> = HashMap::new();
let track_count = self.track_count().await?;
let track_count = self.track_count()?;
let mut result: Vec<(Option<String>, Option<String>, Vec<u16>)> = Vec::new();
let raw_full_title = self.raw_disc_title(true).await?;
let raw_full_title = self._disc_title(true)?;
let mut full_width_group_list = raw_full_title.split("");
@ -911,7 +906,7 @@ impl NetMDInterface {
}
/// Gets a list of track titles from a set
pub async fn track_titles(
pub fn track_titles(
&mut self,
tracks: Vec<u16>,
wchar: bool,
@ -939,7 +934,7 @@ impl NetMDInterface {
)
.unwrap();
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -960,9 +955,9 @@ impl NetMDInterface {
Ok(track_titles)
}
/// Gets the title of a single track at an index
pub async fn track_title(&mut self, track: u16, wchar: bool) -> Result<String, Box<dyn Error>> {
let title = match self.track_titles([track].into(), wchar).await {
/// Gets the title of a track at an index
pub fn track_title(&mut self, track: u16, wchar: bool) -> Result<String, Box<dyn Error>> {
let title = match self.track_titles([track].into(), wchar) {
Ok(titles) => titles[0].clone(),
Err(error) if error.to_string() == "Rejected" => String::new(),
Err(error) => return Err(error),
@ -971,14 +966,10 @@ impl NetMDInterface {
}
// Sets the title of the disc
pub async fn set_disc_title(
&mut self,
title: String,
wchar: bool,
) -> Result<(), Box<dyn Error>> {
let current_title = self.raw_disc_title(wchar).await?;
pub fn set_disc_title(&mut self, title: String, wchar: bool) -> Result<(), Box<dyn Error>> {
let current_title = self._disc_title(wchar)?;
if current_title == title {
return Err("Title is already the same".into());
return Ok(());
}
let new_title: Vec<u8>;
@ -997,7 +988,7 @@ impl NetMDInterface {
let new_len = new_title.len();
if self.net_md_device.vendor_id().await == &0x04dd {
if self.net_md_device.vendor_id() == &0x04dd {
self.change_descriptor_state(&Descriptor::AudioUTOC1TD, &DescriptorAction::OpenWrite)
} else {
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::Close);
@ -1016,7 +1007,7 @@ impl NetMDInterface {
let _ = self.send_query(&mut query, false, false);
if self.net_md_device.vendor_id().await == &0x04dd {
if self.net_md_device.vendor_id() == &0x04dd {
self.change_descriptor_state(&Descriptor::AudioUTOC1TD, &DescriptorAction::Close)
} else {
self.change_descriptor_state(&Descriptor::DiscTitleTD, &DescriptorAction::Close);
@ -1028,7 +1019,7 @@ impl NetMDInterface {
}
/// Sets the title of a track
pub async fn set_track_title(
pub fn set_track_title(
&mut self,
track: u16,
title: String,
@ -1048,7 +1039,7 @@ impl NetMDInterface {
let new_len = new_title.len();
let old_len: u16 = match self.track_title(track, wchar).await {
let old_len: u16 = match self.track_title(track, wchar) {
Ok(current_title) => {
if title == current_title {
return Ok(());
@ -1070,7 +1061,7 @@ impl NetMDInterface {
QueryValue::Array(new_title),
],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let _ = scan_query(
reply,
@ -1082,19 +1073,19 @@ impl NetMDInterface {
}
/// Removes a track from the UTOC
pub async fn erase_track(&mut self, track: u16) -> Result<(), Box<dyn Error>> {
pub fn erase_track(&mut self, track: u16) -> Result<(), Box<dyn Error>> {
let mut query = format_query(
"1840 ff01 00 201001 %w".to_string(),
vec![QueryValue::Number(track as i64)],
)?;
let _result = self.send_query(&mut query, false, false).await;
let _ = self.send_query(&mut query, false, false);
Ok(())
}
/// Moves a track to another position on the disc
pub async fn move_track(&mut self, source: u16, dest: u16) -> Result<(), Box<dyn Error>> {
pub fn move_track(&mut self, source: u16, dest: u16) -> Result<(), Box<dyn Error>> {
let mut query = format_query(
"1843 ff00 00 201001 %w 201001 %w".to_string(),
vec![
@ -1103,17 +1094,12 @@ impl NetMDInterface {
],
)?;
let _result = self.send_query(&mut query, false, false).await;
let _ = self.send_query(&mut query, false, false);
Ok(())
}
async fn raw_track_info(
&mut self,
track: u16,
p1: i32,
p2: i32,
) -> Result<Vec<u8>, Box<dyn Error>> {
fn _track_info(&mut self, track: u16, p1: i32, p2: i32) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead);
let mut query = format_query(
@ -1125,7 +1111,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
"1806 02201001 %?%? %?%? %?%? 1000 00%?0000 %x".to_string(),
@ -1137,7 +1123,7 @@ impl NetMDInterface {
}
/// Gets the length of tracks as a `std::time::Duration` from a set
pub async fn track_lengths(
pub fn track_lengths(
&mut self,
tracks: Vec<u16>,
) -> Result<Vec<std::time::Duration>, Box<dyn Error>> {
@ -1154,7 +1140,7 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -1181,16 +1167,13 @@ impl NetMDInterface {
}
/// Gets the length of a track as a `std::time::Duration`
pub async fn track_length(
&mut self,
track: u16,
) -> Result<std::time::Duration, Box<dyn Error>> {
Ok(self.track_lengths([track].into()).await?[0])
pub fn track_length(&mut self, track: u16) -> Result<std::time::Duration, Box<dyn Error>> {
Ok(self.track_lengths([track].into())?[0])
}
/// Gets the encoding of a track (SP, LP2, LP4)
pub async fn track_encoding(&mut self, track_number: u16) -> Result<Encoding, Box<dyn Error>> {
let raw_value = self.raw_track_info(track_number, 0x3080, 0x0700).await?;
pub fn track_encoding(&mut self, track_number: u16) -> Result<Encoding, Box<dyn Error>> {
let raw_value = self._track_info(track_number, 0x3080, 0x0700)?;
let result = scan_query(raw_value, "07 0004 0110 %b %b".to_string())?;
let final_encoding = match result[0].to_i64() {
@ -1205,13 +1188,13 @@ impl NetMDInterface {
}
/// Gets a track's flags
pub async fn track_flags(&mut self, track: u16) -> Result<u8, Box<dyn Error>> {
pub fn track_flags(&mut self, track: u16) -> Result<u8, Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::AudioContentsTD, &DescriptorAction::OpenRead);
let mut query = format_query(
"1806 01201001 %w ff00 00010008".to_string(),
vec![QueryValue::Number(track as i64)],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1806 01201001 %?%? 10 00 00010008 %b".to_string())?;
@ -1221,10 +1204,10 @@ impl NetMDInterface {
}
/// Gets the disc capacity as a `std::time::Duration`
pub async fn disc_capacity(&mut self) -> Result<[std::time::Duration; 3], Box<dyn Error>> {
pub fn disc_capacity(&mut self) -> Result<[std::time::Duration; 3], Box<dyn Error>> {
self.change_descriptor_state(&Descriptor::RootTD, &DescriptorAction::OpenRead);
let mut query = format_query("1806 02101000 3080 0300 ff00 00000000".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let mut result: [std::time::Duration; 3] = [std::time::Duration::from_secs(0); 3];
// 8003 changed to %?03 - Panasonic returns 0803 instead. This byte's meaning is unknown
@ -1250,7 +1233,7 @@ impl NetMDInterface {
Ok(result)
}
pub async fn recording_parameters(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn recording_parameters(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
self.change_descriptor_state(
&Descriptor::OperatingStatusBlock,
&DescriptorAction::OpenRead,
@ -1260,7 +1243,7 @@ impl NetMDInterface {
vec![],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
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())?;
@ -1272,7 +1255,7 @@ impl NetMDInterface {
/// Gets the bytes of a track
///
/// This can only be executed on an MZ-RH1 / M200
pub async fn save_track_to_array(
pub fn save_track_to_array(
&mut self,
track: u16,
) -> Result<(DiscFormat, u16, Vec<u8>), Box<dyn Error>> {
@ -1281,7 +1264,7 @@ impl NetMDInterface {
vec![QueryValue::Number((track + 1) as i64)],
)?;
let reply = self.send_query(&mut query, false, true).await?;
let reply = self.send_query(&mut query, false, true)?;
let res = scan_query(
reply,
@ -1292,10 +1275,10 @@ impl NetMDInterface {
let codec = res[1].to_i64().unwrap() as u8;
let length = res[2].to_i64().unwrap() as usize;
let result = self.net_md_device.read_bulk(length, 0x10000).await?;
let result = self.net_md_device.read_bulk(length, 0x10000)?;
scan_query(
self.read_reply(false).await?,
self.read_reply(false)?,
"1800 080046 f003010330 0000 1001 %?%? %?%?".to_string(),
)?;
@ -1312,56 +1295,55 @@ impl NetMDInterface {
Ok((format, frames, result))
}
pub async fn disable_new_track_protection(&mut self, val: u16) -> Result<(), Box<dyn Error>> {
pub fn disable_new_track_protection(&mut self, val: u16) -> Result<(), Box<dyn Error>> {
let mut query = format_query(
"1800 080046 f0030103 2b ff %w".to_string(),
vec![QueryValue::Number(val as i64)],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1800 080046 f0030103 2b 00 %?%?".to_string())?;
Ok(())
}
pub async fn enter_secure_session(&mut self) -> Result<(), Box<dyn Error>> {
pub fn enter_secure_session(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("1800 080046 f0030103 80 ff".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1800 080046 f0030103 80 00".to_string())?;
Ok(())
}
pub async fn leave_secure_session(&mut self) -> Result<(), Box<dyn Error>> {
pub fn leave_secure_session(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("1800 080046 f0030103 81 ff".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1800 080046 f0030103 81 00".to_string())?;
Ok(())
}
/**
* Read the leaf ID of the present NetMD device. The leaf ID tells
* which keys the device posesses, which is needed to find out which
* parts of the EKB needs to be sent to the device for it to decrypt
* the root key.
*
* The leaf ID is a 8-byte constant
Read the leaf ID of the present NetMD device. The leaf ID tells
which keys the device posesses, which is needed to find out which
parts of the EKB needs to be sent to the device for it to decrypt
the root key.
The leaf ID is a 8-byte constant
**/
pub async fn leaf_id(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn leaf_id(&mut self) -> Result<Vec<u8>, Box<dyn Error>> {
let mut query = format_query("1800 080046 f0030103 11 ff".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1800 080046 f0030103 11 00 %*".to_string())?;
Ok(res[0].to_vec().unwrap())
}
pub async fn send_key_data(
pub fn send_key_data(
&mut self,
ekbid: i32,
keychain: [[u8; 16]; 2],
keychain: Vec<[u8; 16]>,
depth: i32,
ekbsignature: [u8; 24],
ekbsignature: Vec<u8>,
) -> Result<Vec<u8>, Box<dyn Error>> {
let chainlen = keychain.len();
let databytes = 16 + 16 * chainlen + 24;
@ -1384,11 +1366,11 @@ impl NetMDInterface {
QueryValue::Number(depth as i64),
QueryValue::Number(ekbid as i64),
QueryValue::Array(keychains),
QueryValue::Array(ekbsignature.to_vec()),
QueryValue::Array(ekbsignature),
],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(
reply,
@ -1398,10 +1380,7 @@ impl NetMDInterface {
Ok(res[0].to_vec().unwrap())
}
pub async fn session_key_exchange(
&mut self,
hostnonce: Vec<u8>,
) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn session_key_exchange(&mut self, hostnonce: Vec<u8>) -> Result<Vec<u8>, Box<dyn Error>> {
if hostnonce.len() != 8 {
return Err("Supplied host nonce length wrong".into());
}
@ -1410,23 +1389,23 @@ impl NetMDInterface {
vec![QueryValue::Array(hostnonce)],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1800 080046 f0030103 20 %? 000000 %#".to_string())?;
Ok(res[0].to_vec().unwrap())
}
pub async fn session_key_forget(&mut self) -> Result<(), Box<dyn Error>> {
pub fn session_key_forget(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("1800 080046 f0030103 21 ff 000000".to_string(), vec![])?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let _ = scan_query(reply, "1800 080046 f0030103 21 00 000000".to_string())?;
Ok(())
}
pub async fn setup_download(
pub fn setup_download(
&mut self,
contentid: Vec<u8>,
keyenckey: Vec<u8>,
@ -1453,14 +1432,14 @@ impl NetMDInterface {
vec![QueryValue::Array(encryptedarg)],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1800 080046 f0030103 22 00 0000".to_string())?;
Ok(())
}
pub async fn commit_track(
pub fn commit_track(
&mut self,
track_number: u16,
hex_session_key: String,
@ -1480,14 +1459,14 @@ impl NetMDInterface {
],
)?;
let reply = self.send_query(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
scan_query(reply, "1800 080046 f0030103 22 00 0000".to_string())?;
Ok(())
}
pub async fn send_track(
pub fn send_track(
&mut self,
wireformat: u8,
discformat: u8,
@ -1515,7 +1494,7 @@ impl NetMDInterface {
QueryValue::Number(total_bytes as i64),
],
)?;
let mut reply = self.send_query(&mut query, false, true).await?;
let mut reply = self.send_query(&mut query, false, true)?;
scan_query(
reply,
"1800 080046 f0030103 28 00 000100 1001 %?%? 00 %*".to_string(),
@ -1532,12 +1511,12 @@ impl NetMDInterface {
} else {
data.clone()
};
self.net_md_device.write_bulk(binpack).await?;
self.net_md_device.write_bulk(binpack)?;
_written_bytes += data.len();
}
reply = self.read_reply(false).await?;
self.net_md_device.poll().await?;
reply = self.read_reply(false)?;
self.net_md_device.poll()?;
let res = scan_query(
reply,
"1800 080046 f0030103 28 00 000100 1001 %w 00 %?%? %?%?%?%? %?%?%?%? %*".to_string(),
@ -1556,21 +1535,21 @@ impl NetMDInterface {
Ok((res[0].to_i64().unwrap(), part1, part2))
}
pub async fn track_uuid(&mut self, track: u16) -> Result<String, Box<dyn Error>> {
pub fn track_uuid(&mut self, track: u16) -> Result<String, Box<dyn Error>> {
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(&mut query, false, false).await?;
let reply = self.send_query(&mut query, false, false)?;
let res = scan_query(reply, "1800 080046 f0030103 23 00 1001 %?%? %*".to_string())?;
Ok(String::from_utf8_lossy(&res[0].to_vec().unwrap()).to_string())
}
pub async fn terminate(&mut self) -> Result<(), Box<dyn Error>> {
pub fn terminate(&mut self) -> Result<(), Box<dyn Error>> {
let mut query = format_query("1800 080046 f0030103 2a ff00".to_string(), vec![])?;
self.send_query(&mut query, false, false).await?;
self.send_query(&mut query, false, false)?;
Ok(())
}
@ -1602,43 +1581,39 @@ lazy_static! {
]);
}
pub struct EKBData {
chains: [[u8; 16]; 2],
depth: i32,
signature: [u8; 24],
}
pub struct EKBOpenSource {}
struct EKBOpenSource {}
impl EKBOpenSource {
pub fn root_key(&self) -> [u8; 16] {
fn root_key(&mut self) -> [u8; 16] {
[
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65,
0x43, 0x21,
]
}
pub fn ekb_id(&self) -> i32 {
fn ekb_id(&mut self) -> i32 {
0x26422642
}
pub fn ekb_data_for_leaf_id(&self) -> EKBData {
EKBData {
chains: [
[0x25, 0x45, 0x06, 0x4d, 0xea, 0xca, 0x14, 0xf9, 0x96, 0xbd, 0xc8, 0xa4, 0x06, 0xc2, 0x2b, 0x81],
[0xfb, 0x60, 0xbd, 0xdd, 0x0d, 0xbc, 0xab, 0x84, 0x8a, 0x00, 0x5e, 0x03, 0x19, 0x4d, 0x3e, 0xda],
/* What's this for?
ekb_data_for_leaf_id(): [Uint8Array[], number, Uint8Array] {
return [
[
new Uint8Array([0x25, 0x45, 0x06, 0x4d, 0xea, 0xca, 0x14, 0xf9, 0x96, 0xbd, 0xc8, 0xa4, 0x06, 0xc2, 0x2b, 0x81]),
new Uint8Array([0xfb, 0x60, 0xbd, 0xdd, 0x0d, 0xbc, 0xab, 0x84, 0x8a, 0x00, 0x5e, 0x03, 0x19, 0x4d, 0x3e, 0xda]),
],
depth: 9,
signature: [
9,
new Uint8Array([
0x8f, 0x2b, 0xc3, 0x52, 0xe8, 0x6c, 0x5e, 0xd3, 0x06, 0xdc, 0xae, 0x18,
0xd2, 0xf3, 0x8c, 0x7f, 0x89, 0xb5, 0xe1, 0x85, 0x55, 0xa1, 0x05, 0xea,
],
}
0xd2, 0xf3, 0x8c, 0x7f, 0x89, 0xb5, 0xe1, 0x85, 0x55, 0xa1, 0x05, 0xea
])
];
}
*/
}
#[derive(Clone)]
pub struct MDTrack {
struct MDTrack {
title: String,
format: WireFormat,
data: Vec<u8>,
@ -1648,7 +1623,7 @@ pub struct MDTrack {
}
#[derive(Clone)]
pub struct EncryptPacketsIterator {
struct EncryptPacketsIterator {
kek: Vec<u8>,
frame_size: i32,
data: Vec<u8>,
@ -1700,24 +1675,3 @@ impl MDTrack {
[0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5]
}
}
pub struct MDSession {
md: NetMDInterface,
ekb_object: EKBOpenSource,
hex_session_key: String,
}
impl MDSession {
pub async fn init(&mut self) -> Result<(), Box<dyn Error>>{
self.md.enter_secure_session().await?;
self.md.leaf_id().await?;
let ekb = self.ekb_object.ekb_data_for_leaf_id();
self.md.send_key_data(self.ekb_object.ekb_id(), ekb.chains, ekb.depth, ekb.signature).await?;
let mut nonce = vec![0u8, 8];
rand::thread_rng().fill_bytes(&mut nonce);
// TODO
Ok(())
}
}

View file

@ -193,6 +193,7 @@ lazy_static! {
("".to_string(), "".to_string()),
("".to_string(), "".to_string())
]);
pub static ref MAPPINGS_RU: HashMap<String, String> = HashMap::from([
("а".to_string(), "a".to_string()),
("б".to_string(), "b".to_string()),
@ -261,6 +262,7 @@ lazy_static! {
("Ю".to_string(), "Iu".to_string()),
("Я".to_string(), "Ia".to_string())
]);
pub static ref MAPPINGS_DE: HashMap<String, String> = HashMap::from([
("Ä".to_string(), "Ae".to_string()),
("ä".to_string(), "ae".to_string()),
@ -270,285 +272,287 @@ lazy_static! {
("ü".to_string(), "ue".to_string()),
("ß".to_string(), "ss".to_string())
]);
pub static ref MAPPINGS_HW: HashMap<String, String> = HashMap::from([
("".to_string(), "-".to_string()),
("".to_string(), "-".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ガ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ギ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "グ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゲ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゴ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ザ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ジ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ズ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゼ".to_string()),
("".to_string(), "ソ".to_string()),
("".to_string(), "ゾ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ダ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヂ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヅ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "デ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ド".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "バ".to_string()),
("".to_string(), "パ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ビ".to_string()),
("".to_string(), "ピ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ブ".to_string()),
("".to_string(), "プ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ベ".to_string()),
("".to_string(), "ペ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ボ".to_string()),
("".to_string(), "ポ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "-".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヴ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "!".to_string()),
("".to_string(), "\"".to_string()),
("".to_string(), "#".to_string()),
("".to_string(), "$".to_string()),
("".to_string(), "%".to_string()),
("".to_string(), "&".to_string()),
("".to_string(), "'".to_string()),
("".to_string(), "(".to_string()),
("".to_string(), ")".to_string()),
("".to_string(), "*".to_string()),
("".to_string(), "+".to_string()),
("".to_string(), ",".to_string()),
("".to_string(), ".".to_string()),
("".to_string(), "/".to_string()),
("".to_string(), ":".to_string()),
("".to_string(), ";".to_string()),
("".to_string(), "<".to_string()),
("".to_string(), "=".to_string()),
("".to_string(), ">".to_string()),
("".to_string(), "?".to_string()),
("".to_string(), "@".to_string()),
("".to_string(), "A".to_string()),
("".to_string(), "B".to_string()),
("".to_string(), "C".to_string()),
("".to_string(), "D".to_string()),
("".to_string(), "E".to_string()),
("".to_string(), "F".to_string()),
("".to_string(), "G".to_string()),
("".to_string(), "H".to_string()),
("".to_string(), "I".to_string()),
("".to_string(), "J".to_string()),
("".to_string(), "K".to_string()),
("".to_string(), "L".to_string()),
("".to_string(), "M".to_string()),
("".to_string(), "N".to_string()),
("".to_string(), "O".to_string()),
("".to_string(), "P".to_string()),
("".to_string(), "Q".to_string()),
("".to_string(), "R".to_string()),
("".to_string(), "S".to_string()),
("".to_string(), "T".to_string()),
("".to_string(), "U".to_string()),
("".to_string(), "V".to_string()),
("".to_string(), "W".to_string()),
("".to_string(), "X".to_string()),
("".to_string(), "Y".to_string()),
("".to_string(), "Z".to_string()),
("".to_string(), "[".to_string()),
("".to_string(), "\\".to_string()),
("".to_string(), "]".to_string()),
("".to_string(), "^".to_string()),
("_".to_string(), "_".to_string()),
("".to_string(), "`".to_string()),
("".to_string(), "a".to_string()),
("".to_string(), "b".to_string()),
("".to_string(), "c".to_string()),
("".to_string(), "d".to_string()),
("".to_string(), "e".to_string()),
("".to_string(), "f".to_string()),
("".to_string(), "g".to_string()),
("".to_string(), "h".to_string()),
("".to_string(), "i".to_string()),
("".to_string(), "j".to_string()),
("".to_string(), "k".to_string()),
("".to_string(), "l".to_string()),
("".to_string(), "m".to_string()),
("".to_string(), "n".to_string()),
("".to_string(), "o".to_string()),
("".to_string(), "p".to_string()),
("".to_string(), "q".to_string()),
("".to_string(), "r".to_string()),
("".to_string(), "s".to_string()),
("".to_string(), "t".to_string()),
("".to_string(), "u".to_string()),
("".to_string(), "v".to_string()),
("".to_string(), "w".to_string()),
("".to_string(), "x".to_string()),
("".to_string(), "y".to_string()),
("".to_string(), "z".to_string()),
("".to_string(), "{".to_string()),
("".to_string(), "|".to_string()),
("".to_string(), "}".to_string()),
("".to_string(), "~".to_string()),
(" ".to_string(), " ".to_string()),
("".to_string(), "0".to_string()),
("".to_string(), "1".to_string()),
("".to_string(), "2".to_string()),
("".to_string(), "3".to_string()),
("".to_string(), "4".to_string()),
("".to_string(), "5".to_string()),
("".to_string(), "6".to_string()),
("".to_string(), "7".to_string()),
("".to_string(), "8".to_string()),
("".to_string(), "9".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ガ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ギ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "グ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゲ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゴ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ザ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ジ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ズ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ゼ".to_string()),
("".to_string(), "ソ".to_string()),
("".to_string(), "ゾ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ダ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヂ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヅ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "デ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ド".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "バ".to_string()),
("".to_string(), "パ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ビ".to_string()),
("".to_string(), "ピ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ブ".to_string()),
("".to_string(), "プ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ベ".to_string()),
("".to_string(), "ペ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ボ".to_string()),
("".to_string(), "ポ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "ヴ".to_string()),
("".to_string(), "".to_string()),
("".to_string(), "".to_string()),
("".to_string(),"-".to_string()),
("".to_string(),"-".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ガ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ギ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"グ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゲ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゴ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ザ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ジ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ズ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゼ".to_string()),
("".to_string(),"ソ".to_string()),
("".to_string(),"ゾ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ダ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヂ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヅ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"デ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ド".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"バ".to_string()),
("".to_string(),"パ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ビ".to_string()),
("".to_string(),"ピ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ブ".to_string()),
("".to_string(),"プ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ベ".to_string()),
("".to_string(),"ペ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ボ".to_string()),
("".to_string(),"ポ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"-".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヴ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"!".to_string()),
("".to_string(),"\"".to_string()),
("".to_string(),"#".to_string()),
("".to_string(),"$".to_string()),
("".to_string(),"%".to_string()),
("".to_string(),"&".to_string()),
("".to_string(),"'".to_string()),
("".to_string(),"(".to_string()),
("".to_string(),")".to_string()),
("".to_string(),"*".to_string()),
("".to_string(),"+".to_string()),
("".to_string(),",".to_string()),
("".to_string(),".".to_string()),
("".to_string(),"/".to_string()),
("".to_string(),":".to_string()),
("".to_string(),";".to_string()),
("".to_string(),"<".to_string()),
("".to_string(),"=".to_string()),
("".to_string(),">".to_string()),
("".to_string(),"?".to_string()),
("".to_string(),"@".to_string()),
("".to_string(),"A".to_string()),
("".to_string(),"B".to_string()),
("".to_string(),"C".to_string()),
("".to_string(),"D".to_string()),
("".to_string(),"E".to_string()),
("".to_string(),"F".to_string()),
("".to_string(),"G".to_string()),
("".to_string(),"H".to_string()),
("".to_string(),"I".to_string()),
("".to_string(),"J".to_string()),
("".to_string(),"K".to_string()),
("".to_string(),"L".to_string()),
("".to_string(),"M".to_string()),
("".to_string(),"N".to_string()),
("".to_string(),"O".to_string()),
("".to_string(),"P".to_string()),
("".to_string(),"Q".to_string()),
("".to_string(),"R".to_string()),
("".to_string(),"S".to_string()),
("".to_string(),"T".to_string()),
("".to_string(),"U".to_string()),
("".to_string(),"V".to_string()),
("".to_string(),"W".to_string()),
("".to_string(),"X".to_string()),
("".to_string(),"Y".to_string()),
("".to_string(),"Z".to_string()),
("".to_string(),"[".to_string()),
("".to_string(),"\\".to_string()),
("".to_string(),"]".to_string()),
("".to_string(),"^".to_string()),
("_".to_string(),"_".to_string()),
("".to_string(),"`".to_string()),
("".to_string(),"a".to_string()),
("".to_string(),"b".to_string()),
("".to_string(),"c".to_string()),
("".to_string(),"d".to_string()),
("".to_string(),"e".to_string()),
("".to_string(),"f".to_string()),
("".to_string(),"g".to_string()),
("".to_string(),"h".to_string()),
("".to_string(),"i".to_string()),
("".to_string(),"j".to_string()),
("".to_string(),"k".to_string()),
("".to_string(),"l".to_string()),
("".to_string(),"m".to_string()),
("".to_string(),"n".to_string()),
("".to_string(),"o".to_string()),
("".to_string(),"p".to_string()),
("".to_string(),"q".to_string()),
("".to_string(),"r".to_string()),
("".to_string(),"s".to_string()),
("".to_string(),"t".to_string()),
("".to_string(),"u".to_string()),
("".to_string(),"v".to_string()),
("".to_string(),"w".to_string()),
("".to_string(),"x".to_string()),
("".to_string(),"y".to_string()),
("".to_string(),"z".to_string()),
("".to_string(),"{".to_string()),
("".to_string(),"|".to_string()),
("".to_string(),"}".to_string()),
("".to_string(),"~".to_string()),
(" ".to_string()," ".to_string()),
("".to_string(),"0".to_string()),
("".to_string(),"1".to_string()),
("".to_string(),"2".to_string()),
("".to_string(),"3".to_string()),
("".to_string(),"4".to_string()),
("".to_string(),"5".to_string()),
("".to_string(),"6".to_string()),
("".to_string(),"7".to_string()),
("".to_string(),"8".to_string()),
("".to_string(),"9".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ガ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ギ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"グ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゲ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゴ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ザ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ジ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ズ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ゼ".to_string()),
("".to_string(),"ソ".to_string()),
("".to_string(),"ゾ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ダ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヂ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヅ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"デ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ド".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"バ".to_string()),
("".to_string(),"パ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ビ".to_string()),
("".to_string(),"ピ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ブ".to_string()),
("".to_string(),"プ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ベ".to_string()),
("".to_string(),"ペ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ボ".to_string()),
("".to_string(),"ポ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"ヴ".to_string()),
("".to_string(),"".to_string()),
("".to_string(),"".to_string()),
]);
pub static ref ALLOWED_HW_KANA: Vec<String> = MAPPINGS_HW.values().cloned().collect();
}

View file

@ -6,7 +6,6 @@
mod base;
pub mod interface;
mod mappings;
mod query_utils;
mod utils;
mod commands;
mod mappings;

View file

@ -3,7 +3,7 @@ use lazy_static::lazy_static;
use std::collections::hash_map::HashMap;
use std::error::Error;
lazy_static! {
lazy_static!{
/// %b, w, d, q - explained above (can have endiannes overriden by '>' and '<' operators, f. ex. %>d %<q)
/// %s - Uint8Array preceded by 2 bytes of length
/// %x - Uint8Array preceded by 2 bytes of length
@ -44,7 +44,10 @@ impl QueryValue {
}
/// Formats a query using a standard input to send to the player
pub fn format_query(format: String, args: Vec<QueryValue>) -> Result<Vec<u8>, Box<dyn Error>> {
pub fn format_query(
format: String,
args: Vec<QueryValue>,
) -> Result<Vec<u8>, Box<dyn Error>> {
if DEBUG {
println!("SENT>>> F: {}", format);
}

View file

@ -59,7 +59,9 @@ pub fn half_width_to_full_width_range(range: &str) -> String {
.collect()
}
pub fn get_bytes<const S: usize>(iterator: &mut IntoIter<u8>) -> Result<[u8; S], Box<dyn Error>> {
pub fn get_bytes<const S: usize>(
iterator: &mut IntoIter<u8>,
) -> Result<[u8; S], Box<dyn Error>> {
let byte_vec: Vec<u8> = iterator.take(S).collect();
let bytes: [u8; S] = byte_vec.try_into().unwrap();
@ -168,7 +170,5 @@ pub fn agressive_sanitize_title(title: &str) -> String {
pub fn time_to_duration(time: &Vec<u64>) -> std::time::Duration {
assert_eq!(time.len(), 4);
std::time::Duration::from_micros(
(time[0] * 3600000000) + (time[1] * 60000000) + (time[2] * 1000000) + (time[3] * 11600),
)
std::time::Duration::from_micros((time[0] * 3600000000) + (time[1] * 60000000) + (time[2] * 1000000) + (time[3] * 11600))
}

View file

@ -1,15 +1,14 @@
use minidisc_rs::netmd::interface;
use nusb;
#[tokio::main]
async fn main() {
fn main() {
let devices = nusb::list_devices().unwrap();
for device in devices {
// Ensure the player is a minidisc player and not some other random device
let mut player_controller = match interface::NetMDInterface::new(&device).await {
let mut player_controller = match interface::NetMDInterface::new(&device) {
Ok(player) => player,
Err(err) => continue,
Err(_) => continue,
};
println!(
@ -23,25 +22,22 @@ async fn main() {
player_controller
.net_md_device
.device_name()
.await
.clone()
.unwrap()
);
let now = std::time::Instant::now();
let half_title = player_controller.disc_title(false).await.unwrap_or("".to_string());
let full_title = player_controller.disc_title(true).await.unwrap_or("".to_string());
println!(
"Disc Title: {} | {}",
half_title,
full_title
player_controller
.disc_title(false)
.unwrap_or("".to_string()),
player_controller.disc_title(true).unwrap_or("".to_string())
);
let track_count = player_controller.track_count().await.unwrap();
println!("{}", track_count);
let track_titles = player_controller.track_titles((0..track_count).collect(), false).await.unwrap();
let track_titlesw = player_controller.track_titles((0..track_count).collect(), true).await.unwrap();
let track_lengths = player_controller.track_lengths((0..track_count).collect()).await.unwrap();
let track_count = player_controller.track_count().unwrap();
let track_titles = player_controller.track_titles((0..track_count).collect(), false).unwrap();
let track_titlesw = player_controller.track_titles((0..track_count).collect(), true).unwrap();
let track_lengths = player_controller.track_lengths((0..track_count).collect()).unwrap();
for (i, track) in track_titles.iter().enumerate() {
println!(
"Track {i} Info:\n Title: {track} | {}\n Length: {:?}",