mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-04-20 04:02:53 -05:00
Compare commits
4 commits
4aee02c150
...
0d9646c5a0
Author | SHA1 | Date | |
---|---|---|---|
0d9646c5a0 | |||
630a8c95eb | |||
e7d21253d8 | |||
c563a41781 |
7 changed files with 46 additions and 44 deletions
|
@ -10,11 +10,8 @@ license = "AGPL-3.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
cross_usb = { path = "/home/g2/Documents/projects/code/rust/cross-usb/" }
|
cross_usb = "0.1"
|
||||||
[target.'cfg(target_family = "wasm")'.dependencies]
|
tokio = { version = "1.35.1", features = ["macros", "rt", "rt-multi-thread"] }
|
||||||
tokio = { version = "1.35.1", features = ["macros"] }
|
|
||||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
|
||||||
tokio = { version = "1.35.1", features = ["full"] }
|
|
||||||
|
|
||||||
[dependencies.minidisc_rs]
|
[dependencies.minidisc_rs]
|
||||||
path = "minidisc-rs"
|
path = "minidisc-rs"
|
||||||
|
|
|
@ -21,7 +21,7 @@ unicode-normalization = "0.1.22"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
regex = "1.10.2"
|
regex = "1.10.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
cross_usb = { path = "../../cross-usb/" }
|
cross_usb = "0.1"
|
||||||
num-derive = "0.3.3"
|
num-derive = "0.3.3"
|
||||||
num-traits = "0.2.14"
|
num-traits = "0.2.14"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
|
|
|
@ -4,16 +4,12 @@ use once_cell::sync::Lazy;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
|
||||||
use gloo::{
|
|
||||||
timers::future::TimeoutFuture,
|
|
||||||
console::log,
|
|
||||||
};
|
|
||||||
|
|
||||||
// USB stuff
|
// USB stuff
|
||||||
//use nusb::transfer::{Control, ControlIn, ControlOut, ControlType, Recipient, RequestBuffer};
|
//use nusb::transfer::{Control, ControlIn, ControlOut, ControlType, Recipient, RequestBuffer};
|
||||||
use cross_usb::context::{UsbDevice, UsbInterface};
|
use cross_usb::{UsbDevice, UsbInterface};
|
||||||
use cross_usb::usb::{ControlIn, ControlOut, ControlType, Device, Interface, Recipient};
|
use cross_usb::usb::{ControlIn, ControlOut, ControlType, Device, Interface, Recipient};
|
||||||
|
|
||||||
|
use super::utils::cross_sleep;
|
||||||
//use nusb::{Device, DeviceInfo, Interface};
|
//use nusb::{Device, DeviceInfo, Interface};
|
||||||
|
|
||||||
const DEFAULT_TIMEOUT: Duration = Duration::new(10000, 0);
|
const DEFAULT_TIMEOUT: Duration = Duration::new(10000, 0);
|
||||||
|
@ -243,26 +239,24 @@ impl NetMD {
|
||||||
use_factory_command: bool,
|
use_factory_command: bool,
|
||||||
override_length: Option<i32>,
|
override_length: Option<i32>,
|
||||||
) -> Result<Vec<u8>, Box<dyn Error>> {
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
let mut length = self.poll().await?.0;
|
let mut length = 0;
|
||||||
|
|
||||||
for attempt in 0..75 {
|
for attempt in 0..40 {
|
||||||
if attempt == 75 {
|
if attempt == 39 {
|
||||||
return Err("Failed to get response length".into());
|
return Err("Failed to get response length".into());
|
||||||
}
|
}
|
||||||
// Back off while trying again
|
|
||||||
let sleep_time = Self::READ_REPLY_RETRY_INTERVAL as u64
|
|
||||||
* (u64::pow(2, attempt as u32 / 10) - 1);
|
|
||||||
|
|
||||||
#[cfg(not(target_family = "wasm"))]
|
|
||||||
std::thread::sleep(std::time::Duration::from_millis(sleep_time));
|
|
||||||
|
|
||||||
#[cfg(target_family = "wasm")]
|
|
||||||
TimeoutFuture::new(sleep_time as u32).await;
|
|
||||||
|
|
||||||
length = self.poll().await?.0;
|
length = self.poll().await?.0;
|
||||||
|
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Back off while trying again
|
||||||
|
let sleep_time = Self::READ_REPLY_RETRY_INTERVAL
|
||||||
|
* (u32::pow(2, attempt / 10) - 1);
|
||||||
|
|
||||||
|
cross_sleep(sleep_time).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(value) = override_length {
|
if let Some(value) = override_length {
|
||||||
|
@ -328,7 +322,7 @@ impl NetMD {
|
||||||
Ok(final_result)
|
Ok(final_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write_bulk(&mut self, data: Vec<u8>) -> Result<usize, Box<dyn Error>> {
|
pub async fn write_bulk(&mut self, data: &[u8]) -> Result<usize, Box<dyn Error>> {
|
||||||
self.usb_interface.bulk_out(BULK_WRITE_ENDPOINT, data).await
|
self.usb_interface.bulk_out(BULK_WRITE_ENDPOINT, data).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#![cfg_attr(debug_assertions, allow(dead_code))]
|
#![cfg_attr(debug_assertions, allow(dead_code))]
|
||||||
use std::{error::Error, thread::sleep, time::Duration};
|
use std::error::Error;
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
use super::interface::{NetMDInterface, MDTrack};
|
use super::interface::{NetMDInterface, MDTrack};
|
||||||
|
use super::utils::cross_sleep;
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive)]
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -59,7 +60,7 @@ pub async fn device_status(interface: &mut NetMDInterface) -> Result<DeviceStatu
|
||||||
|
|
||||||
pub async fn prepare_download(interface: &mut NetMDInterface) -> Result<(), Box<dyn Error>>{
|
pub async fn prepare_download(interface: &mut NetMDInterface) -> Result<(), Box<dyn Error>>{
|
||||||
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(&device_status(interface).await?.state.unwrap_or(OperatingStatus::NoDisc)) {
|
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(&device_status(interface).await?.state.unwrap_or(OperatingStatus::NoDisc)) {
|
||||||
sleep(Duration::from_millis(200));
|
cross_sleep(200).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = interface.session_key_forget().await;
|
let _ = interface.session_key_forget().await;
|
||||||
|
|
|
@ -13,8 +13,8 @@ use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::thread::sleep;
|
|
||||||
use std::time::Duration;
|
use super::utils::cross_sleep;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
enum Action {
|
enum Action {
|
||||||
|
@ -204,7 +204,7 @@ impl NetMDInterface {
|
||||||
const MAX_INTERIM_READ_ATTEMPTS: u8 = 4;
|
const MAX_INTERIM_READ_ATTEMPTS: u8 = 4;
|
||||||
const INTERIM_RESPONSE_RETRY_INTERVAL: u32 = 100;
|
const INTERIM_RESPONSE_RETRY_INTERVAL: u32 = 100;
|
||||||
|
|
||||||
pub async fn new(device: &cross_usb::context::UsbDevice) -> Result<Self, Box<dyn Error>> {
|
pub async fn new(device: &cross_usb::UsbDevice) -> Result<Self, Box<dyn Error>> {
|
||||||
let net_md_device = base::NetMD::new(device).await?;
|
let net_md_device = base::NetMD::new(device).await?;
|
||||||
Ok(NetMDInterface { net_md_device })
|
Ok(NetMDInterface { net_md_device })
|
||||||
}
|
}
|
||||||
|
@ -387,10 +387,11 @@ impl NetMDInterface {
|
||||||
NetmdStatus::NotImplemented => return Err("Not implemented".into()),
|
NetmdStatus::NotImplemented => return Err("Not implemented".into()),
|
||||||
NetmdStatus::Rejected => return Err("Rejected".into()),
|
NetmdStatus::Rejected => return Err("Rejected".into()),
|
||||||
NetmdStatus::Interim if !accept_interim => {
|
NetmdStatus::Interim if !accept_interim => {
|
||||||
let sleep_time = Self::INTERIM_RESPONSE_RETRY_INTERVAL as u64
|
let sleep_time = Self::INTERIM_RESPONSE_RETRY_INTERVAL
|
||||||
* (u64::pow(2, current_attempt as u32) - 1);
|
* (u32::pow(2, current_attempt as u32) - 1);
|
||||||
let sleep_dur = std::time::Duration::from_millis(sleep_time);
|
|
||||||
std::thread::sleep(sleep_dur); // Sleep to wait before retrying
|
cross_sleep(sleep_time).await;
|
||||||
|
|
||||||
current_attempt += 1;
|
current_attempt += 1;
|
||||||
continue; // Retry!
|
continue; // Retry!
|
||||||
}
|
}
|
||||||
|
@ -987,7 +988,7 @@ impl NetMDInterface {
|
||||||
|
|
||||||
let wchar_value = match wchar {
|
let wchar_value = match wchar {
|
||||||
true => {
|
true => {
|
||||||
new_title = sanitize_full_width_title(&title, false);
|
new_title = sanitize_full_width_title(title, false);
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
|
@ -1038,11 +1039,11 @@ impl NetMDInterface {
|
||||||
let new_title: Vec<u8>;
|
let new_title: Vec<u8>;
|
||||||
let (wchar_value, descriptor) = match wchar {
|
let (wchar_value, descriptor) = match wchar {
|
||||||
true => {
|
true => {
|
||||||
new_title = sanitize_full_width_title(&title, false);
|
new_title = sanitize_full_width_title(title, false);
|
||||||
(3, Descriptor::AudioUTOC4TD)
|
(3, Descriptor::AudioUTOC4TD)
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
new_title = sanitize_half_width_title(title.clone());
|
new_title = sanitize_half_width_title(title);
|
||||||
(2, Descriptor::AudioUTOC1TD)
|
(2, Descriptor::AudioUTOC1TD)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1503,7 +1504,7 @@ impl NetMDInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sharps are slow
|
// Sharps are slow
|
||||||
sleep(Duration::from_millis(200));
|
cross_sleep(200).await;
|
||||||
|
|
||||||
let total_bytes = pkt_size + 24; //framesizedict[wireformat] * frames + pktcount * 24;
|
let total_bytes = pkt_size + 24; //framesizedict[wireformat] * frames + pktcount * 24;
|
||||||
|
|
||||||
|
@ -1523,7 +1524,7 @@ impl NetMDInterface {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Sharps are slow
|
// Sharps are slow
|
||||||
sleep(Duration::from_millis(200));
|
cross_sleep(200).await;
|
||||||
|
|
||||||
let mut _written_bytes = 0;
|
let mut _written_bytes = 0;
|
||||||
for (packet_count, (key, iv, data)) in packets.into_iter().enumerate() {
|
for (packet_count, (key, iv, data)) in packets.into_iter().enumerate() {
|
||||||
|
@ -1533,7 +1534,7 @@ impl NetMDInterface {
|
||||||
} else {
|
} else {
|
||||||
data.clone()
|
data.clone()
|
||||||
};
|
};
|
||||||
self.net_md_device.write_bulk(binpack).await?;
|
self.net_md_device.write_bulk(&binpack).await?;
|
||||||
_written_bytes += data.len();
|
_written_bytes += data.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,15 @@ use unicode_normalization::UnicodeNormalization;
|
||||||
extern crate kana;
|
extern crate kana;
|
||||||
use kana::*;
|
use kana::*;
|
||||||
|
|
||||||
|
/// Sleep for a specified number of milliseconds on any platform
|
||||||
|
pub async fn cross_sleep(millis: u32) {
|
||||||
|
#[cfg(not(target_family = "wasm"))]
|
||||||
|
std::thread::sleep(std::time::Duration::from_millis(millis as u64));
|
||||||
|
|
||||||
|
#[cfg(target_family = "wasm")]
|
||||||
|
gloo::timers::future::TimeoutFuture::new(millis).await;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bcd_to_int(mut bcd: i32) -> i32 {
|
pub fn bcd_to_int(mut bcd: i32) -> i32 {
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let mut nibble = 0;
|
let mut nibble = 0;
|
||||||
|
@ -90,7 +99,7 @@ fn check(string: String) -> Option<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sanitize_half_width_title(title: &str) -> Vec<u8> {
|
pub fn sanitize_half_width_title(title: &str) -> Vec<u8> {
|
||||||
let mut string_title = wide2ascii(&title);
|
let mut string_title = wide2ascii(title);
|
||||||
string_title = nowidespace(&string_title);
|
string_title = nowidespace(&string_title);
|
||||||
string_title = hira2kata(&string_title);
|
string_title = hira2kata(&string_title);
|
||||||
string_title = combine(&string_title);
|
string_title = combine(&string_title);
|
||||||
|
@ -107,7 +116,7 @@ pub fn sanitize_half_width_title(title: &str) -> Vec<u8> {
|
||||||
let sjis_string = SHIFT_JIS.encode(&new_title).0;
|
let sjis_string = SHIFT_JIS.encode(&new_title).0;
|
||||||
|
|
||||||
if validate_shift_jis(sjis_string.clone().into()) {
|
if validate_shift_jis(sjis_string.clone().into()) {
|
||||||
return agressive_sanitize_title(&title).into();
|
return agressive_sanitize_title(title).into();
|
||||||
}
|
}
|
||||||
|
|
||||||
sjis_string.into()
|
sjis_string.into()
|
||||||
|
|
|
@ -3,7 +3,7 @@ use cross_usb::usb::Device;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let device = cross_usb::context::get_device(0x054c, 0x0186).await.unwrap();
|
let device = cross_usb::get_device(0x054c, 0x0186).await.unwrap();
|
||||||
|
|
||||||
dbg!(device.vendor_id().await);
|
dbg!(device.vendor_id().await);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue