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"
|
||||
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"]
|
||||
|
|
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 hex;
|
||||
use magic_crypt::{new_magic_crypt, MagicCrypt, MagicCryptTrait, SecureBit};
|
||||
use rand::RngCore;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
|
||||
|
@ -442,7 +443,7 @@ impl NetMDInterface {
|
|||
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 reply = self.send_query(&mut query, false, false)?;
|
||||
|
||||
|
@ -451,7 +452,7 @@ impl NetMDInterface {
|
|||
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 reply = self.send_query(&mut query, false, false)?;
|
||||
|
@ -1341,9 +1342,9 @@ impl NetMDInterface {
|
|||
pub fn send_key_data(
|
||||
&mut self,
|
||||
ekbid: i32,
|
||||
keychain: Vec<[u8; 16]>,
|
||||
keychain: [[u8; 16]; 2],
|
||||
depth: i32,
|
||||
ekbsignature: Vec<u8>,
|
||||
ekbsignature: [u8; 24],
|
||||
) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||
let chainlen = keychain.len();
|
||||
let databytes = 16 + 16 * chainlen + 24;
|
||||
|
@ -1366,7 +1367,7 @@ impl NetMDInterface {
|
|||
QueryValue::Number(depth as i64),
|
||||
QueryValue::Number(ekbid as i64),
|
||||
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 {
|
||||
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,
|
||||
0x43, 0x21,
|
||||
]
|
||||
}
|
||||
|
||||
fn ekb_id(&mut self) -> i32 {
|
||||
pub fn ekb_id(&self) -> i32 {
|
||||
0x26422642
|
||||
}
|
||||
|
||||
/* 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]),
|
||||
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],
|
||||
],
|
||||
9,
|
||||
new Uint8Array([
|
||||
depth: 9,
|
||||
signature: [
|
||||
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)]
|
||||
struct MDTrack {
|
||||
pub struct MDTrack {
|
||||
title: String,
|
||||
format: WireFormat,
|
||||
data: Vec<u8>,
|
||||
|
@ -1623,7 +1628,7 @@ struct MDTrack {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct EncryptPacketsIterator {
|
||||
pub struct EncryptPacketsIterator {
|
||||
kek: Vec<u8>,
|
||||
frame_size: i32,
|
||||
data: Vec<u8>,
|
||||
|
@ -1675,3 +1680,24 @@ 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 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 utils;
|
||||
mod mappings;
|
||||
mod commands;
|
||||
|
|
Loading…
Reference in a new issue