use std::convert::TryInto;
use anyhow::Result;
use bytes::Bytes;
use clap::Parser;
use minidsp::{
commands::{BytesWrap, Commands, ExtendView, FloatView, MemoryView},
eeprom, source, MiniDSP,
};
use super::{parse_hex, parse_hex_u16};
pub(crate) async fn run_debug(device: &MiniDSP<'_>, debug: &DebugCommands) -> Result<()> {
match debug {
DebugCommands::Send { value } => {
let response = device
.client
.roundtrip(Commands::Unknown {
cmd_id: value[0],
payload: BytesWrap(value.slice(1..)),
})
.await?;
println!("response: {:02x?}", response);
}
&DebugCommands::Dump { addr, end_addr } => {
let mut view = MemoryView {
base: addr,
data: Default::default(),
};
let end_addr = end_addr.unwrap_or(59);
for i in (addr..end_addr).step_by(59) {
view.extend_with(device.client.read_memory(i, 59).await?)?;
}
println!("\n");
dump_memory(&view);
}
&DebugCommands::DumpFloat { addr, end_addr } => {
let len = 14;
let end_addr = end_addr.unwrap_or(14);
for i in (addr..end_addr).step_by(14) {
let view = device.client.read_floats(i, len as u8).await?;
dump_floats(&view);
}
}
DebugCommands::Id => {
#[cfg(feature = "hid")]
{
use minidsp::transport::hid;
println!("Probing local hid devices:");
let api = hid::initialize_api()?;
let mut api = api.lock().unwrap();
let devices = hid::discover(&mut api)?;
if devices.is_empty() {
println!("No matching local USB devices detected.")
} else {
for device in &devices {
println!("Found: {}", device);
}
}
println!()
}
let device_info = device.get_device_info().await?;
println!(
"HW ID: {}\nDSP Version: {}",
device_info.hw_id, device_info.dsp_version
);
let sources = source::Source::mapping(&device_info);
println!("Detected sources: {:?}", sources);
println!("\nDumping memory:");
let mut view = device.client.read_memory(0xffa0, 59).await?;
view.extend_with(device.client.read_memory(0xffa0 + 59, 59).await?)?;
dump_memory(&view);
println!("\n\nDumping readable floats:");
for addr in (0x00..0xff).step_by(14) {
let floats = device.client.read_floats(addr, 14).await?;
dump_floats(&floats);
}
}
&DebugCommands::SetSerial { value } => {
if !(900000..=965535).contains(&900000) {
return Err(anyhow::anyhow!("Serial must be between 900000 and 965535"));
}
let value: u16 = (value - 900000).try_into().unwrap();
device.client.write_u16(eeprom::SERIAL_SHORT, value).await?;
}
}
std::process::exit(0);
}
fn dump_memory(view: &MemoryView) {
use hexplay::HexViewBuilder;
println!("len={:?}", view.data.len());
let view = HexViewBuilder::new(view.data.as_ref())
.address_offset(view.base as usize)
.row_width(16)
.finish();
view.print().unwrap();
}
fn dump_floats(view: &FloatView) {
for i in view.base..(view.base + view.data.len() as u16) {
let val = view.get(i);
if val != 0. {
println!("{:04x?}: {:?}", i, val);
}
}
}
#[derive(Clone, Parser, Debug)]
pub enum DebugCommands {
Send {
#[clap(parse(try_from_str = parse_hex))]
value: Bytes,
},
Dump {
#[clap(parse(try_from_str = parse_hex_u16))]
addr: u16,
#[clap(parse(try_from_str = parse_hex_u16))]
end_addr: Option<u16>,
},
DumpFloat {
#[clap(parse(try_from_str = parse_hex_u16))]
addr: u16,
#[clap(parse(try_from_str = parse_hex_u16))]
end_addr: Option<u16>,
},
Id,
SetSerial { value: u32 },
}