mirror of
https://github.com/G2-Games/minidisc-cli.git
synced 2025-04-19 11:42:53 -05:00
Merge pull request #3 from asivery/main
Add basic commands, start working on track upload
This commit is contained in:
commit
922d8a5cb3
4 changed files with 129 additions and 23 deletions
|
@ -25,7 +25,9 @@ regex = "1.10.2"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
nusb = "0.1.4"
|
nusb = "0.1.4"
|
||||||
futures-lite = "2.2.0"
|
futures-lite = "2.2.0"
|
||||||
|
num-derive = "0.3.3"
|
||||||
|
num-traits = "0.2.14"
|
||||||
|
rand = "0.8.5"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|
77
minidisc-rs/src/netmd/commands.rs
Normal file
77
minidisc-rs/src/netmd/commands.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
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 fn device_status(interface: &mut NetMDInterface) -> Result<DeviceStatus, Box<dyn Error>> {
|
||||||
|
let status = interface.status()?;
|
||||||
|
let playback_status = interface.playback_status2()?;
|
||||||
|
let b1: u16 = playback_status[4] as u16;
|
||||||
|
let b2: u16 = playback_status[5] as u16;
|
||||||
|
let position = interface.position()?;
|
||||||
|
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 fn prepare_download(interface: &mut NetMDInterface) -> Result<(), Box<dyn Error>>{
|
||||||
|
while ![OperatingStatus::DiscBlank, OperatingStatus::Ready].contains(&device_status(interface)?.state.or(Some(OperatingStatus::NoDisc)).unwrap()) {
|
||||||
|
sleep(Duration::from_millis(200));
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = interface.session_key_forget();
|
||||||
|
let _ = interface.leave_secure_session();
|
||||||
|
|
||||||
|
interface.acquire()?;
|
||||||
|
let _ = interface.disable_new_track_protection(1);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn download(interface: &mut NetMDInterface, track: MDTrack) -> Result<(), Box<dyn Error>>{
|
||||||
|
prepare_download(interface)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ use crate::netmd::utils::{
|
||||||
use encoding_rs::*;
|
use encoding_rs::*;
|
||||||
use hex;
|
use hex;
|
||||||
use magic_crypt::{new_magic_crypt, MagicCrypt, MagicCryptTrait, SecureBit};
|
use magic_crypt::{new_magic_crypt, MagicCrypt, MagicCryptTrait, SecureBit};
|
||||||
|
use rand::RngCore;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
@ -442,7 +443,7 @@ impl NetMDInterface {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn acquire(&mut self) -> Result<(), Box<dyn Error>> {
|
pub 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 mut query = format_query("ff 010c ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
|
||||||
|
@ -451,7 +452,7 @@ impl NetMDInterface {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn release(&mut self) -> Result<(), Box<dyn Error>> {
|
pub 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 mut query = format_query("ff 0100 ffff ffff ffff ffff ffff ffff".to_string(), vec![])?;
|
||||||
|
|
||||||
let reply = self.send_query(&mut query, false, false)?;
|
let reply = self.send_query(&mut query, false, false)?;
|
||||||
|
@ -1341,9 +1342,9 @@ impl NetMDInterface {
|
||||||
pub fn send_key_data(
|
pub fn send_key_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
ekbid: i32,
|
ekbid: i32,
|
||||||
keychain: Vec<[u8; 16]>,
|
keychain: [[u8; 16]; 2],
|
||||||
depth: i32,
|
depth: i32,
|
||||||
ekbsignature: Vec<u8>,
|
ekbsignature: [u8; 24],
|
||||||
) -> Result<Vec<u8>, Box<dyn Error>> {
|
) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
let chainlen = keychain.len();
|
let chainlen = keychain.len();
|
||||||
let databytes = 16 + 16 * chainlen + 24;
|
let databytes = 16 + 16 * chainlen + 24;
|
||||||
|
@ -1366,7 +1367,7 @@ impl NetMDInterface {
|
||||||
QueryValue::Number(depth as i64),
|
QueryValue::Number(depth as i64),
|
||||||
QueryValue::Number(ekbid as i64),
|
QueryValue::Number(ekbid as i64),
|
||||||
QueryValue::Array(keychains),
|
QueryValue::Array(keychains),
|
||||||
QueryValue::Array(ekbsignature),
|
QueryValue::Array(ekbsignature.to_vec()),
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -1581,39 +1582,43 @@ lazy_static! {
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EKBOpenSource {}
|
pub struct EKBData {
|
||||||
|
chains: [[u8; 16]; 2],
|
||||||
|
depth: i32,
|
||||||
|
signature: [u8; 24],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct EKBOpenSource {}
|
||||||
|
|
||||||
impl EKBOpenSource {
|
impl EKBOpenSource {
|
||||||
fn root_key(&mut self) -> [u8; 16] {
|
pub fn root_key(&self) -> [u8; 16] {
|
||||||
[
|
[
|
||||||
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65,
|
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x0f, 0xed, 0xcb, 0xa9, 0x87, 0x65,
|
||||||
0x43, 0x21,
|
0x43, 0x21,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ekb_id(&mut self) -> i32 {
|
pub fn ekb_id(&self) -> i32 {
|
||||||
0x26422642
|
0x26422642
|
||||||
}
|
}
|
||||||
|
|
||||||
/* What's this for?
|
pub fn ekb_data_for_leaf_id(&self) -> EKBData {
|
||||||
ekb_data_for_leaf_id(): [Uint8Array[], number, Uint8Array] {
|
EKBData {
|
||||||
return [
|
chains: [
|
||||||
[
|
[0x25, 0x45, 0x06, 0x4d, 0xea, 0xca, 0x14, 0xf9, 0x96, 0xbd, 0xc8, 0xa4, 0x06, 0xc2, 0x2b, 0x81],
|
||||||
new Uint8Array([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],
|
||||||
new Uint8Array([0xfb, 0x60, 0xbd, 0xdd, 0x0d, 0xbc, 0xab, 0x84, 0x8a, 0x00, 0x5e, 0x03, 0x19, 0x4d, 0x3e, 0xda]),
|
|
||||||
],
|
],
|
||||||
9,
|
depth: 9,
|
||||||
new Uint8Array([
|
signature: [
|
||||||
0x8f, 0x2b, 0xc3, 0x52, 0xe8, 0x6c, 0x5e, 0xd3, 0x06, 0xdc, 0xae, 0x18,
|
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)]
|
#[derive(Clone)]
|
||||||
struct MDTrack {
|
pub struct MDTrack {
|
||||||
title: String,
|
title: String,
|
||||||
format: WireFormat,
|
format: WireFormat,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -1623,7 +1628,7 @@ struct MDTrack {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct EncryptPacketsIterator {
|
pub struct EncryptPacketsIterator {
|
||||||
kek: Vec<u8>,
|
kek: Vec<u8>,
|
||||||
frame_size: i32,
|
frame_size: i32,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
|
@ -1675,3 +1680,24 @@ impl MDTrack {
|
||||||
[0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5]
|
[0x14, 0xe3, 0x83, 0x4e, 0xe2, 0xd3, 0xcc, 0xa5]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct MDSession {
|
||||||
|
md: NetMDInterface,
|
||||||
|
ekb_object: EKBOpenSource,
|
||||||
|
hex_session_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MDSession {
|
||||||
|
pub fn init(&mut self) -> Result<(), Box<dyn Error>>{
|
||||||
|
self.md.enter_secure_session()?;
|
||||||
|
self.md.leaf_id()?;
|
||||||
|
|
||||||
|
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)?;
|
||||||
|
let mut nonce = vec![0u8, 8];
|
||||||
|
rand::thread_rng().fill_bytes(&mut nonce);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,3 +9,4 @@ pub mod interface;
|
||||||
mod query_utils;
|
mod query_utils;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod mappings;
|
mod mappings;
|
||||||
|
mod commands;
|
||||||
|
|
Loading…
Reference in a new issue